Sự khác biệt giữa loại Tùy chọn và loại Nullable là gì


12

Swift có Optionals. C # có Nullablecác loại.

Theo như tôi có thể nói cả hai đều phục vụ cùng một mục đích, bên cạnh giá trị của một số loại họ lưu trữ thông tin cho dù biến có giá trị hay không được xác định (chưa được khởi tạo).

Câu hỏi Optionalschỉ là Nullablecác loại có tên khác nhau hoặc có sự khác biệt về khái niệm khác?

Nói cách khác, nói về khái niệm chính nó, hoặc trong bối cảnh các ngôn ngữ không có Optionalshoặc Nullables, liệu vấn đề này có được sử dụng không?

Khi thực hiện chức năng đó trong ngôn ngữ, vấn đề là tôi đặt tên loại Optionals<T>hayNullable<T>


Từ quan điểm bất khả tri ngôn ngữ, chúng giống hệt nhau. Điều đó nói rằng, một ngôn ngữ có thể phân biệt các khái niệm (ví dụ: Có hay không việc khớp mẫu được thi hành).
Thomas Eding 2/2/2015

C # cũng có thể có Tùy chọn (đó chỉ là một mẫu đơn âm): github.com/louthy/lingu-ext
Den

2
Sử dụng tham chiếu null (hoặc con trỏ NULL, trong các ngôn ngữ có con trỏ) là một hack mà một số ngôn ngữ sử dụng để biểu thị các giá trị tùy chọn, tức là một thùng chứa có thể có một giá trị hoặc không có giá trị nào cả. Điều này có giới hạn là bạn chỉ có thể xem xét một loại tùy chọn dựa trên tài liệu tham khảo (hoặc con trỏ). Vì vậy, ví dụ, trong Java, bạn không thể tạo một số nguyên tùy chọn mà không gói nó trong một đối tượng (ví dụ: Integer). Các ngôn ngữ khác cung cấp các loại tùy chọn dưới dạng các loại chung có thể bao bọc bất kỳ loại nào khác, ví dụ: Có thể trong Haskell, Tùy chọn trong Scala, v.v.
Giorgio

Câu trả lời:


5

Có một ý nghĩa khác nhau, mặc dù chúng hoạt động rất giống nhau. Tất cả mọi người trừ Microsoft (chèn eye-roll vào đây) sử dụng nullnullablechỉ trong bối cảnh tham chiếu. OptionsMaybesthường được hiểu là đề cập đến cả tham chiếu và giá trị, đặc biệt là trong các ngôn ngữ lập trình chức năng nơi tính minh bạch tham chiếu có nghĩa là không có nhiều khác biệt giữa giá trị và tham chiếu.

Nói cách khác, nói về khái niệm chính nó, hoặc trong bối cảnh các ngôn ngữ không có Optionalshoặc Nullables, vấn đề nào được sử dụng?

Optionslà thuật ngữ gây ra sự nhầm lẫn ít nhất trong số các đối tượng rộng. Chỉ các lập trình viên C # sẽ nghĩ về một Nullablekhả năng áp dụng cho một loại giá trị và tôi nghĩ rằng hầu hết trong số họ ít nhất nhận thức được những gì là một Option.


Tất cả mọi người trừ Microsoft và các nhà thiết kế SQL, tôi nghĩ bạn có ý đó.
Jules

9

Trong .NET, có hai loại kiểu: tham chiếugiá 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 : structmệnh đề). Nullable<>cũng có khả năng đặc biệt từ trình biên dịch, theo đó một nullgiá 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 nullmộ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 Optionloại (danh pháp khác nhau, nó được gọi Maybetrong Haskell). Điều này thực hiện một công việc tương tự như Nullabletrong đó 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.mapxâ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.maphà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;

C # là một ngôn ngữ chức năng không tinh khiết (giống như F #). Ngoài ra F # có null.
Den

C # 6 có giá trị null ép buộc, vì vậy ít nhất một số mã của bạn không được cập nhật: github.com/dotnet/roslyn/wiki/... roslyn.codeplex.com/discussions/540883
Den

Ngoài ra, các tùy chọn rất dễ thực hiện: github.com/louthy/lingu-ext
Den

1
@Den: C # nghiêng về OOP trong khi F # nghiêng về phía FP. Thiếu cà ri và khả năng biến đổi theo mặc định có nghĩa là C # không phù hợp với lập trình chức năng nghiêm trọng. Tôi đã đề cập đến việc truyền bá null ở cuối câu trả lời. Các tùy chọn thực sự đơn giản để thực hiện trong C # nhưng điều đó đi lạc khỏi câu hỏi.
AlexFoxGill 2/2/2015

4
@ Tôi nghĩ rằng có một số lựa chọn từ kém trong ý kiến ​​của bạn. Một ngôn ngữ chức năng không tinh khiết là một ngôn ngữ chức năng cho phép tác dụng phụ. C # có thể có một số tính năng chức năng và bạn có thể sử dụng chúng để có hiệu quả tuyệt vời, nhưng đó không phải là ngôn ngữ chức năng. Tôi đoán bạn có nghĩa là không ngôn ngữ nào có chức năng 100%, nhưng F # rất gần với OCaml, phần lớn là ngôn ngữ chức năng. Bất kỳ sai lệch nào mà nó tạo ra từ mô hình chức năng hầu hết đều tồn tại để nó có thể tương tác với mã .NET nước ngoài. Trường hợp tại điểm, nullkhông phải là một giá trị hợp lệ cho các loại F #.
Doval 2/2/2015
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.