2013-08-15 33 views
92

Tại sao cụm từ này không biên dịch?Không thể xác định loại biểu thức có điều kiện vì không có chuyển đổi tiềm ẩn giữa 'int' và <null>

int? number = true ? 5 : null; 

Loại biểu thức điều kiện không xác định được vì không có chuyển đổi ngầm giữa 'int' và < rỗng >

+0

Giải thích và ví dụ tốt nhất ... [http://stackoverflow.com/questions/858080/nullable-types-and-the-ternary-operator-why-is-10-null-forbidden?answertab=active#tab ] (http://stackoverflow.com/questions/858080/nullable-types-and-the-ternary-operator-why-is-10-null-forbidden?answertab=active#tab-top) -top –

Trả lời

194

Thông số kỹ thuật (§7.14) nói rằng đối với điều kiện cũ pression b ? x : y, có ba khả năng, hoặc là xy cả hai đều có một loại nhất định điều kiện tốt được đáp ứng, chỉ là một trong xy có một loại nhất định điều kiện tốt được đáp ứng, hoặc một biên dịch lỗi thời gian xảy ra. Ở đây, "một số điều kiện tốt" có nghĩa là một số chuyển đổi nhất định có thể thực hiện được, chúng tôi sẽ đưa vào các chi tiết bên dưới.

Bây giờ, chúng ta hãy chuyển sang phần Gecman của spec:

Nếu chỉ một trong xy có một loại, và cả hai xy đang ngầm chuyển đổi thành kiểu đó, thì đó là loại của biểu thức có điều kiện.

Vấn đề ở đây là trong

int? number = true ? 5 : null; 

chỉ một trong những kết quả có điều kiện có một kiểu. Dưới đây là một xint theo nghĩa đen, và ynull mà không không có một loại null không phải là mặc nhiên chuyển đổi thành một int . Do đó, "điều kiện tốt nhất định" không được đáp ứng và xảy ra lỗi biên dịch.

hai cách xung quanh này:

int? number = true ? (int?)5 : null; 

Ở đây chúng ta vẫn còn trong trường hợp chỉ có một trong xy có một kiểu. Lưu ý rằng nullvẫn còn không có loại nào nhưng trình biên dịch sẽ không gặp bất kỳ vấn đề nào với điều này vì (int?)5null đều được chuyển đổi hoàn toàn thành int? (§6.1.4 và §6.1.5).

Một cách khác là rõ ràng:

int? number = true ? 5 : (int?)null; 

nhưng bây giờ chúng ta phải đọc một khác nhau khoản trong spec để hiểu tại sao điều này không quan trọng:

Nếu x đã gõ Xy có loại Y rồi

  • Nếu chuyển đổi tiềm ẩn (§6.1) tồn tại từ X đến Y, nhưng không phải từ Y đến X, thì Y là loại biểu thức có điều kiện.

  • Nếu một chuyển đổi ngầm (§6.1) tồn tại Y-X, nhưng không X-Y, sau đó X là kiểu của biểu thức điều kiện.

  • Nếu không, không thể xác định loại biểu thức nào và xảy ra lỗi biên dịch.

Đây x là loại inty là loại int?. Không có chuyển đổi tiềm ẩn từ int? đến int, nhưng có một chuyển đổi tiềm ẩn từ int đến int? do đó loại biểu thức là int?.

: Lưu ý thêm rằng loại bên trái được bỏ qua trong việc xác định loại biểu thức có điều kiện, một nguồn gây nhầm lẫn phổ biến ở đây.

+3

Trích dẫn tốt thông số để minh họa tại sao điều này xảy ra - +1! – JerKimball

+1

Một tùy chọn khác là 'new int?()' Thay cho '(int?) Null'. – Guvante

+1

Đây cũng là trường hợp nếu bạn có loại trường cơ sở dữ liệu có thể vô hiệu hóa, ví dụ DateTime có thể vô hiệu hóa và bạn thử và truyền dữ liệu đến 'DateTime', khi nó yêu cầu' (DateTime?) ' –

38

null không có bất kỳ loại cá - nó chỉ cần một chút prodding để làm cho nó hạnh phúc:

int? number = true ? 5 : (int?)null; 
+1

Hoặc bạn có thể làm 'int? number = true? 5: null như int?; ' –

+0

Câu trả lời hay là đóng đinh điểm. Tốt đẹp liên quan đến đọc: http://ericlippert.com/2013/05/30/what-the-meaning-of-is-is/ –

+0

Vấn đề là * không * rằng 'null' không có một loại có thể nhận dạng. Vấn đề là không có chuyển đổi ngầm từ 'null' sang' int'. Chi tiết [tại đây] (http://stackoverflow.com/a/18260915/45914). – jason