2010-01-08 23 views
13

Bạn đã bao giờ thử sử dụng phương pháp Convert.ChangeType() để chuyển đổi giá trị thành loại Nullable<T>? Lúng túng, nó sẽ ném một InvalidCastException nói rằng "Null đối tượng không thể được chuyển đổi thành một loại giá trị".Tại sao Nullable <T> được coi là một loại giá trị?

Cố gắng chạy này trên cửa sổ trước mắt của bạn: ?System.Convert.ChangeType(null, typeof(int?))

kiểu giá trị Đối với một số lý do mơ hồ, Nullables được xem xét. Ví dụ: typeof(int?).IsValueType trả về true.

Đối với tôi, kể từ Nullable<T> chấp nhận null, đây là loại lớp, không phải là loại giá trị. Có ai biết tại sao nó sẽ được thực hiện khác nhau?

Trả lời

27

System.Nullable<T> là về mặt kỹ thuật một cấu trúc, vì vậy đó là một kiểu giá trị (giá trị null cho một Nullable<T> không phải là chính xác những điều tương tự như một tham chiếu null. Đó là một lá cờ boolean biểu thị sự thiếu một giá trị.) Tuy nhiên, nó được xử lý đặc biệt bởi thời gian chạy và điều này làm cho nó trở thành một loại giá trị khó xử. Đầu tiên, nó không đáp ứng ràng buộc loại where T : struct (nó không đáp ứng where T : class hoặc là, cho những gì nó có giá trị). Thứ hai, nó thể hiện một hành vi đấm bốc thú vị. Boxing một Nullable<T> sẽ cho kết quả:

  • Tham chiếu null, nếu giá trị là null.
  • Giá trị đóng hộp của loại cơ bản nếu giá trị thực sự chứa giá trị. Tức là, trong các phát biểu:

    int? x = 2; 
    object y = x; 
    

    y không phải là đóng hộp Nullable<int>. Nó chỉ đơn giản là một đóng hộp int. Bạn có thể bỏ hộp bất kỳ giá trị được đóng gói nào của loại T thành Nullable<T> (và T, tất nhiên). Đúc một tham chiếu null tới Nullable<T> dẫn đến giá trị null (như bạn có thể mong đợi).

Cách xử lý đặc biệt này theo thời gian chạy làm cho các loại vô hiệu hoạt động tương tự như cách null hoạt động trong các loại tham chiếu.

+3

Hành vi đấm bốc lạ thường mất một thời gian để hiểu - nhưng tôi rất vui vì đó là cách của nó; nếu không nhiều giá trị của 'Nullable ' (xuất phát từ tính trong suốt giá trị) sẽ bị mất. – LBushkin

+1

Trên thực tế, hành vi quyền anh là một thay đổi xảy ra muộn trong chu kỳ phát triển .NET 2.0. Trong bản beta đầu tiên, 'Nullable ' là một cấu trúc đơn giản. Trong thực tế khi bạn thực sự sử dụng các kiểu nullable để lưu trữ các giá trị không tồn tại, tôi cũng cảm thấy hành vi này là tự nhiên hơn. –

+0

Thông tin bổ sung tuyệt vời bằng cách này – Nick

11

Nullable<T> là một loại giá trị (đó là một cấu trúc, nhìn thấy trong MSDN documentation), nhưng có một chuyển đổi ngầm từ null đến một Nullable<T> mà không có một giá trị (x.HasValue == false). Ngoài ra còn có chuyển đổi tiềm ẩn từ các giá trị thuộc loại T thành các giá trị loại Nullable<T>.

Ngoài ra, tất cả các toán tử đều được loại bỏ khỏi các loại thông thường để làm việc trực tiếp với các loại không có giá trị.

+0

Tại sao bạn nên downvote? Tôi sai? Nếu có, xin hãy khai sáng cho tôi. –

+0

Tôi đã bỏ phiếu để hủy bỏ ghi chú. :) –

2

Nullable<T> được triển khai dưới dạng cấu trúc và cấu trúc là các loại giá trị.

+1

Nhưng không cấu trúc nào có thể nhận giá trị 'null'. Tôi tin rằng Nullables là đủ khác nhau từ các cấu trúc để không được coi là cấu trúc. – jpbochi

+2

'Nullable ' không thể nhận giá trị 'null', nó chỉ có một chuyển đổi ngầm đến và từ' null'. Bạn có thể thực hiện điều này trên bất kỳ 'struct' tùy chỉnh nào, nếu bạn muốn. – Aaronaught

+4

@Aaronaught: bạn có thể làm điều gì đó * tương tự * với cấu trúc tùy chỉnh, nhưng rất nhiều hành vi của các loại nullable không thể được bắt chước thông qua mã. Các giá trị không thể bỏ qua không chỉ là giải pháp thư viện. Họ nhận được hỗ trợ đặc biệt từ trình biên dịch (và CLR quá, tôi nghĩ). –

1

Tôi vừa thấy câu hỏi này trong danh sách "câu hỏi có liên quan" tại Why Nullable<T> is a struct? và tôi nghĩ câu trả lời của tôi cũng áp dụng ở đây. Toàn bộ điểm của Nullable<T> là hoạt động như một loại giá trị trong mọi khía cạnh ngoại trừ khả năng lấy giá trị null.

Không có tham chiếu null trong hai cách.Một là nó không ám chỉ cái gì cả, khác là nó không có giá trị ý nghĩa. Những điều này là khá nhiều hai cách khác nhau để nói cùng một điều, nhưng họ có cách sử dụng khác nhau.

Nullable<T> cho chúng tôi khả năng nói "điều này không có giá trị có ý nghĩa" và mức độ đó có thể có cùng ngữ nghĩa như tham chiếu null, nhưng không giống như tham chiếu theo bất kỳ cách nào khác. Khi null nó là nullity hoàn toàn là "không có giá trị có ý nghĩa" null - không "không đề cập đến bất cứ điều gì" và khi không null nó đang nắm giữ một giá trị, không đề cập đến nó.

(Aaronaught lập luận rằng điều này có nghĩa một Nullable có thể không thực sự chứa null, trong khi tôi không đồng ý vì ở cấp độ mà nó sử dụng nó có thể có một null ngữ nghĩa, quan điểm của mình rất đáng xem xét ở chỗ ngay cả khi "null" một Nullable khác với tham chiếu - thực sự sự bất đồng của chúng tôi là vấn đề mà mức độ trừu tượng mà chúng tôi chọn để sử dụng).

Các vấn đề liên quan