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


Câu trả lời:


337

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

Bây giờ, hãy chuyển sang phần nguyên bản của thông số kỹ thuật:

Nếu chỉ có một xycó một loại, và cả hai xyhoàn toàn có thể chuyển đổi thành loại đó, thì đó là loại biểu thức điều kiện.

Vấn đề ở đây là

int? number = true ? 5 : null;

chỉ một trong những kết quả có điều kiện có một loại. Dưới đây xlà một intchữ, và ynullkhông có một loại nullkhông phải là mặc nhiên chuyển đổi thành một int1 . Do đó, "một số điều kiện tốt" không được đáp ứng và xảy ra lỗi thời gian biên dịch.

được 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 xycó một loại. Lưu ý rằng null vẫn không có một loại chưa trình biên dịch sẽ không có bất kỳ vấn đề với điều này bởi vì (int?)5nullcả hai đều mặc nhiên chuyển đổi thành int?(§6.1.4 và §6.1.5).

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

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

nhưng bây giờ chúng ta phải đọc một mệnh đề khác trong thông số kỹ thuật để hiểu tại sao điều này lại ổn:

Nếu xcó loại Xycó loại Ythì

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

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

  • Mặt khác, không có loại biểu thức nào có thể được xác định và xảy ra lỗi thời gian biên dịch.

Đây xlà loại intylà loại int?. Không có chuyển đổi ngầm định từ int?sang int, nhưng có một chuyển đổi ngầm định từ intthành int?nên loại biểu thức là int?.

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


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

7
Một lựa chọn khác là new int?()ở chỗ (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 không thể rỗng, ví dụ như DateTime không thể rỗng và bạn thử và truyền dữ liệu đến DateTime, khi nó không bắt buộc(DateTime?)
Mike Upjohn

73

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

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

2
Hoặc bạn có thể làmint? number = true ? 5 : null as int?;
Brad M

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

Vấn đề không phảinullkhông có loại nhận dạng. Vấn đề là không có chuyển đổi ngầm định từ nullsang int. Chi tiết tại đây .
jason

điều thú vị là int? number = true ? 5 : (int?)null;int? number = true ? (int?)5 : null;cả biên dịch !! Cào, cào
davidhq

2
Tôi bao gồm chính xác lý do tại sao điều này xảy ra trong câu trả lời của tôi .
jason

4

Như những người khác đã đề cập, 5 là một int, và nullkhông thể được chuyển đổi hoàn toàn thành int.

Dưới đây là các cách khác để khắc phục sự cố:

int? num = true ? 5 : default(int?);
int? num = true ? 5 : new int?();

int? num = true ? 5 : null as int?;
int? num = true ? 5 : (int?)null;

int? num = true ? (int?)5 : null;
int? num = true ? 5 as int? : null;

int? num = true ? new int?(5) : null;

Ngoài ra, bất cứ nơi nào bạn nhìn thấy int?, bạn cũng có thể sử dụng Nullable<int>.


1

Trong blogC# 9 này hiện đã được cho phép

Mục tiêu đánh máy ?? và?

Đôi khi có điều kiện ?? và ?: biểu thức không có kiểu chia sẻ rõ ràng giữa các nhánh. Những trường hợp như vậy thất bại ngày hôm nay, nhưng C # 9.0 sẽ cho phép chúng nếu có một loại mục tiêu mà cả hai nhánh chuyển đổi thành:

Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type

Hoặc ví dụ của bạn:

// Allowed in C# 9.
int? number = true ? 5 : null;
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.