Rõ ràng Nullable<int>và int?có giá trị tương đương. Có lý do nào để chọn cái này hơn cái kia không?
Nullable<int> a = null;
int? b = null;
a == b; // this is true
Rõ ràng Nullable<int>và int?có giá trị tương đương. Có lý do nào để chọn cái này hơn cái kia không?
Nullable<int> a = null;
int? b = null;
a == b; // this is true
Câu trả lời:
Biểu ?mẫu chỉ là cách viết tắt của loại đầy đủ. Sở thích cá nhân là lý do duy nhất để chọn cái này hơn cái kia.
Chi tiết đầy đủ tại đây .
Cú pháp
T?là viết tắt củaNullable<T>, đâuTlà kiểu giá trị. Hai hình thức có thể thay thế cho nhau.
Trong khi tôi hoàn toàn đồng ý rằng trong nhiều trường hợp họ đều giống nhau, tôi vừa đi qua một tình huống, khi có là một sự khác biệt giữa hai. Để biết thêm chi tiết, hãy xem câu hỏi này , nhưng để cung cấp cho bạn một ví dụ nhanh ở đây:
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
}
Dòng đầu tiên đưa ra các thông báo lỗi sau:
error CS1003: Syntax error, ':' expected
error CS1525: Invalid expression term ';'
Nếu bạn tò mò về lý do chính xác cho điều này, tôi thực sự khuyên bạn nên kiểm tra câu hỏi đã được liên kết , nhưng vấn đề cơ bản là trong giai đoạn phân tích cú pháp sau một is(hoặc một as) toán tử, khi chúng ta gặp một ?mã thông báo, chúng ta sẽ kiểm tra xem tiếp theo mã thông báo có thể được hiểu là toán tử một ngôi ( &có thể là một) và nếu vậy: trình phân tích cú pháp không quan tâm đến khả năng ?mã thông báo là một công cụ sửa đổi kiểu, nó chỉ sử dụng kiểu trước nó và sẽ phân tích cú pháp phần còn lại như thể ?mã thông báo là một toán tử bậc ba (do đó phân tích cú pháp sẽ không thành công).
Vì vậy, trong khi nói chung int?và Nullable<int>có thể hoán đổi cho nhau, có một số trường hợp góc khi chúng tạo ra các kết quả hoàn toàn khác nhau, do cách trình phân tích cú pháp nhìn thấy mã của bạn.
test, được cố định bằng dấu ngoặc đơn, vì vậy var test = (a is int?) & b;. Cũng có thể được sửa với var test = a is int? && b;, và cho rằng đó blà một tham số giá trị đơn giản (không có tác dụng phụ khi đánh giá) thì có vẻ lạ hơn là thích &hơn &&.
?là một ký tự chính.
int?như một phép toán bậc ba ( var test = a is int? <return if true> : <return if false>), không phải là một int nullable.
boolquá tải cụ thể này . Đây là các toán tử logic Boolean ( &for bool) và toán tử logic có điều kiện Boolean ( &&for bool). Lưu ý cách phần đầu tiên trong số các phần phụ này được đặt tên logic rõ ràng . Hãy nhớ rằng, trong C # không có chuyển đổi ("phôi") giữa boolvà kiểu số!
Rõ ràng là có sự khác biệt giữa hai cách này khi sử dụng tạo Khung thực thể đầu tiên (EF):
Khi thực thể của bạn chứa một thuộc tính được khai báo như:
public class MyEntity
{
public Nullable<int> MyNullableInt { get; set; }
}
EF sẽ không tạo thuộc tính nullable và bạn sẽ phải buộc trình tạo làm cho nó có thể nullable như sau:
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();
}
}
Mặt khác, nếu bạn khai báo pháp nhân của mình như:
public class MyEntity
{
public int? MyNullableInt { get; set; }
}
trình tạo EF sẽ tạo thuộc tính nullable với trường nullable trong bảng cơ sở dữ liệu tương ứng.
Nullableđịnh nghĩa khác ở đâu đó, bởi vì với tính năng tích hợp Nullable<T>, EF không thể thấy sự khác biệt giữa hai định nghĩa này. Ngay cả khi các thành viên EF muốn đối xử khác với họ, họ không thể.
Nullable là một kiểu chung, nhưng int? không phải.
Có một số trường hợp mà Nullable nên được sử dụng trên int?
ví dụ: ở đây bạn không thể thay thế Nullable bằng int?
Làm thế nào bạn có thể thay đổi mã bên dưới mà không sử dụng 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>nóNullable<int>