เห็นได้ชัดNullable<int>และint?มีมูลค่าเทียบเท่า มีเหตุผลใดบ้างที่ต้องเลือกอย่างใดอย่างหนึ่ง?
Nullable<int> a = null;
int? b = null;
a == b; // this is true
เห็นได้ชัดNullable<int>และint?มีมูลค่าเทียบเท่า มีเหตุผลใดบ้างที่ต้องเลือกอย่างใดอย่างหนึ่ง?
Nullable<int> a = null;
int? b = null;
a == b; // this is true
คำตอบ:
ไม่แตกต่าง.
int?เป็นเพียงชวเลขที่ตัวเองเป็นชวเลขNullable<int>Nullable<Int32>
โค้ดที่คอมไพล์จะเหมือนกับโค้ดที่คุณเลือกใช้
ในขณะที่ฉันสมบูรณ์ตกลงว่าในกรณีส่วนใหญ่พวกเขาจะเหมือนกันที่ฉันเพิ่งมาในสถานการณ์เมื่อมีคือความแตกต่างระหว่างทั้งสอง สำหรับรายละเอียดเกี่ยวกับเลือดโปรดดูคำถามนี้แต่เพื่อให้คุณเป็นตัวอย่างโดยย่อที่นี่:
void Test<T>(T a, bool b)
{
var test = a is int? & b; // does not compile
var test2 = a is Nullable<int> & b; // does compile
}
บรรทัดแรกแสดงข้อความแสดงข้อผิดพลาดต่อไปนี้:
error CS1003: Syntax error, ':' expected
error CS1525: Invalid expression term ';'
หากคุณสงสัยเกี่ยวกับเหตุผลที่แท้จริงสำหรับสิ่งนี้ฉันขอแนะนำให้คุณตรวจสอบคำถามที่เชื่อมโยงอยู่แล้วแต่ปัญหาพื้นฐานคือในขั้นตอนการแยกวิเคราะห์หลังจากตัวดำเนินการis(หรือตัวas) เมื่อเราเผชิญหน้ากับ?โทเค็นเราจะตรวจสอบว่าถัดไปโทเค็นสามารถตีความได้ว่าเป็นตัวดำเนินการยูนารี ( &อาจเป็นหนึ่งตัว) และถ้าเป็นเช่นนั้น: ตัวแยกวิเคราะห์ไม่สนใจเกี่ยวกับความเป็นไปได้ที่?โทเค็นจะเป็นตัวปรับเปลี่ยนประเภทเพียงแค่ใช้ประเภทก่อนหน้านั้นและจะแยกวิเคราะห์ส่วนที่เหลือราวกับว่า?โทเค็นเป็นตัวดำเนินการที่เกี่ยวข้อง (ดังนั้นการแยกวิเคราะห์จะล้มเหลว)
ดังนั้นในขณะที่โดยทั่วไปint?และNullable<int>สามารถใช้แทนกันได้มีบางกรณีที่ให้ผลลัพธ์ที่แตกต่างกันโดยสิ้นเชิงเนื่องจากการที่โปรแกรมแยกวิเคราะห์เห็นรหัสของคุณ
test var test = (a is int?) & b;นอกจากนี้ยังสามารถแก้ไขด้วยvar test = a is int? && b;และระบุว่าbเป็นค่าพารามิเตอร์ง่าย (ไม่มีผลข้างเคียงกับการประเมินผล) มันดูเหมือนว่าแปลกที่จะชอบมากกว่า& &&
?นั้นเป็นอักขระหลัก
int?ว่าเป็นการดำเนินการ ternary ( var test = a is int? <return if true> : <return if false>) ไม่ใช่ int ที่เป็นโมฆะ
boolโอเวอร์โหลดโดยเฉพาะเหล่านี้ เหล่านี้คือตัวดำเนินการตรรกะบูลีน ( &สำหรับbool) และตัวดำเนินการตรรกะแบบมีเงื่อนไขบูลีน ( &&สำหรับbool) สังเกตว่าส่วนย่อยแรกเหล่านี้ตั้งชื่ออย่างชัดเจนว่าตรรกะอย่างไร โปรดจำไว้ว่าใน C # ไม่มีการแปลง ("ร่าย") ระหว่างboolและประเภทตัวเลข!
เห็นได้ชัดว่ามีความแตกต่างระหว่างทั้งสองเมื่อใช้การสร้าง Entity Framework (EF) แรกของโค้ด:
เมื่อเอนทิตีของคุณมีคุณสมบัติที่ประกาศเช่น:
public class MyEntity
{
public Nullable<int> MyNullableInt { get; set; }
}
EF จะไม่สร้างคุณสมบัติที่เป็นโมฆะและคุณจะต้องบังคับให้เครื่องกำเนิดไฟฟ้าทำให้เป็นโมฆะดังนี้:
public class YourContext : DbContext
{
public DbSet<MyEntity> MyEntities{ get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<MyEntity>().Property(x => x.MyNullableInt).IsOptional();
}
}
ในทางกลับกันหากคุณประกาศนิติบุคคลของคุณเช่น:
public class MyEntity
{
public int? MyNullableInt { get; set; }
}
ตัวสร้าง EF จะสร้างคุณสมบัติที่เป็นโมฆะพร้อมกับฟิลด์ที่ว่างเปล่าในตารางฐานข้อมูลที่เกี่ยวข้อง
Nullableคำจำกัดความอื่น ๆอยู่ที่ไหนสักแห่งเพราะในตัวNullable<T>มันเป็นไปไม่ได้ที่ EF จะเห็นความแตกต่างระหว่างทั้งสอง แม้ว่าคน EF จะต้องการปฏิบัติต่อพวกเขาอย่างแตกต่างกัน แต่ก็ทำไม่ได้
Nullableเป็นประเภททั่วไป แต่int? ไม่ใช่.
มีบางสถานการณ์ที่ควรใช้Nullableกับint?
เช่น: ที่นี่คุณไม่สามารถแทนที่Nullableด้วยint?
คุณจะเปลี่ยนรหัสด้านล่างโดยไม่ใช้Nullable ได้อย่างไร?
class LazyValue<T> where T : struct
{
private Nullable<T> val;
private Func<T> getValue;
// Constructor.
public LazyValue(Func<T> func)
{
val = null;
getValue = func;
}
public T Value
{
get
{
if (val == null)
// Execute the delegate.
val = getValue();
return (T)val;
}
}
}
Nullable<T>มันNullable<int>