Trong .NET, có hai loại kiểu: tham chiếu và giá trị (int, double, structs, enums, v.v.). Trong số các khác biệt của chúng là thực tế là một tham chiếu có thể null
, trong khi một giá trị không thể. Do đó, nếu bạn có một loại giá trị và muốn truyền đạt ngữ nghĩa "tùy chọn" hoặc "không xác định", bạn có thể tô điểm cho nó Nullable<>
. Lưu ý rằng Nullable<>
bị ràng buộc bởi loại để chỉ chấp nhận các loại giá trị (nó có một where T : struct
mệnh đề). Nullable<>
cũng có khả năng đặc biệt từ trình biên dịch, theo đó một null
giá trị được bảo vệ khỏi NullReferenceExceptions
:
string x = null;
x.ToString(); // throws a NullReferenceException
int? y = null;
y.ToString(); // returns ""
Trong các ngôn ngữ chức năng (như Scala, F #, Haskell, Swift vv) người ta thường cho null
đến không tồn tại . Điều này là do trên toàn bộ mọi người coi sự tồn tại của null
một ý tưởng tồi và các nhà thiết kế ngôn ngữ đã quyết định giải quyết vấn đề này bằng cách không cho phép nó.
Điều này có nghĩa là một lần nữa chúng ta cần một số cách để thể hiện một giá trị không trong các ngôn ngữ này. Nhập Option
loại (danh pháp khác nhau, nó được gọi Maybe
trong Haskell). Điều này thực hiện một công việc tương tự như Nullable
trong đó nó bao bọc một loại để thêm trường hợp giá trị là "Không" hoặc "Không xác định", v.v.
Sự khác biệt thực sự nằm ở các chức năng bổ sung được cung cấp cho bạn bởi các ngôn ngữ triển khai Option
. Ví dụ: lấy Option.map
(trong mã giả):
function Option<T2> Option.map(opt: Option<T1>, mapFunc: T1 -> T2) {
if (opt is None) return None
else return Option<T2>(mapFunc(opt.Value))
}
Các chức năng Option.map
xâu chuỗi như là một cách mạnh mẽ để tránh bản tóm tắt kiểm tra null điển hình mà bạn thấy ở mọi nơi trong C #:
if (service == null)
return null;
var x = service.GetValue();
if (x == null || x.Property == null)
return null;
return x.Property.Value;
Tương đương Nullable trong C # sẽ là:
public static Nullable<T2> Map<T1, T2>(this Nullable<T1> nullable, Func<T1, T2> f)
where T1 : struct
where T2 : struct
{
if (!nullable.HasValue) return (T2?)null;
else return (T2?) f(nullable.Value);
}
Tuy nhiên, điều này có tiện ích hạn chế trong C # vì nó sẽ chỉ hoạt động cho các loại giá trị.
Phiên bản mới của C # cung cấp toán tử "null lan truyền" ( ?.
) tương tự như Option.map
hàm ngoại trừ nó chỉ áp dụng cho các phương thức và các bộ truy cập thuộc tính. Mẫu trên sẽ được viết lại
return service?.GetValue()?.Property?.Value;