Tại sao tăng Nullable <int> không đưa ra một ngoại lệ?


98

Bạn có thể vui lòng giải thích, tại sao Console.WriteLine viết dòng trống ( Console.WriteLine(null)cho tôi lỗi biên dịch) và tại sao không có NullReferenceException (thậm chí a+=1không nên nâng nó lên)?

int? a = null;
a++; // Why there is not NullReferenceException? 
Console.WriteLine(a); // Empty line

Tất cả ba nhà khai thác ++, +=+đã dỡ bỏ các biến thể. Do đó các báo cáo a++;, a += 1;a = a + 1;tất cả đều được cho phép. Mỗi sản phẩm null(không có ngoại lệ được ném) nếu alà ban đầu null.
Jeppe Stig Nielsen

5
NullReferenceException? nhưng int?không phải là một Reference, nó chỉ là một intcó thể có nullgiá trị
Khaled.K

Câu trả lời:


124

Bạn đang quan sát các tác động của một người vận hành được nâng lên .

Từ phần 7.3.7 của đặc tả C # 5:

Các toán tử nâng lên cho phép các toán tử được xác định trước và do người dùng xác định hoạt động trên các kiểu giá trị không thể nullable cũng được sử dụng với các dạng có thể vô hiệu của các kiểu đó. Các toán tử nâng được xây dựng từ các toán tử được xác định trước và do người dùng xác định đáp ứng các yêu cầu nhất định, như được mô tả trong phần sau:

  • Đối với toán tử + ++ - -- ! ~ một ngôi, tồn tại một dạng toán tử nâng lên nếu kiểu toán hạng và kết quả đều là kiểu giá trị không thể nullable. Dạng nâng lên được xây dựng bằng cách thêm một công cụ ?sửa đổi duy nhất vào các kiểu toán hạng và kết quả. Toán tử được nâng lên tạo ra giá trị null nếu toán hạng là null. Nếu không, toán tử được nâng lên sẽ mở toán hạng, áp dụng toán tử cơ bản và kết thúc kết quả.

Vì vậy, về cơ bản, a++trong trường hợp này là một biểu thức với kết quả là null(như là một int?) và biến được giữ nguyên.

Khi bạn gọi

Console.WriteLine(a);

đang được đóng hộp vào object, chuyển đổi nó thành tham chiếu rỗng, được in dưới dạng dòng trống.


3
Có cách nào để in "null" mà không cần sử dụng Console.WriteLine(a == null ? "null" : a)không?
Cole Johnson

5
@Cole Johnson: Console.WriteLine (a ?? "null"); :)
David Chappelle

2
@DavidChappelle Khi athuộc loại int?, tôi sẽ nói rằng a ?? "null"không tìm thấy loại chung nào cho hai toán hạng. Bạn cần một gợi ý objectlà loại thông dụng. Vì vậy, ép một trong hai toán hạng đó. Di achúc được đóng hộp. Ví dụ ((object)a) ?? "null"hoặc a ?? (object)"null".
Jeppe Stig Nielsen

siêu. bạn có thể liên kết với thông số kỹ thuật? chúng ta có thể xác định điều này khi chúng ta nạp chồng các toán tử trong các lớp của chúng ta không?
Phil

@teabaggs: Tôi không thể liên kết dễ dàng ngay bây giờ và liên kết sẽ chỉ là tài liệu Word (bạn có thể dễ dàng tìm thấy bằng cách tìm kiếm). Bạn tự động nhận được các toán tử được nâng lên khi bạn xác định quá tải của toán tử, nếu thích hợp.
Jon Skeet

116

Câu trả lời của Jon là đúng nhưng tôi sẽ thêm một số lưu ý bổ sung.

Tại sao Console.WriteLine(null)đưa ra lỗi biên dịch?

Có 19 quá tải Console.WriteLinevà ba trong số chúng có thể áp dụng cho a null: một lấy a string, một lấy a char[]và một lấy a object. C # không thể xác định ý của bạn trong ba điều này, vì vậy nó sẽ báo lỗi. Console.WriteLine((object)null)sẽ hợp pháp bởi vì bây giờ nó đã rõ ràng.

tại sao lại Console.WriteLine(a)viết một dòng trống?

alà một null int?. Quá tải giải quyết chọn objectphiên bản của phương pháp, do đó, int?được đóng hộp thành tham chiếu rỗng. Vì vậy, điều này về cơ bản giống như Console.WriteLine((object)null), viết một dòng trống.

Tại sao không có NullReferenceExceptiontrên gia số?

Tham chiếu rỗng mà bạn đang lo lắng ở đâu? alà một null int?không phải là một kiểu tham chiếu để bắt đầu! Hãy nhớ rằng, kiểu giá trị nullable là kiểu giá trị , không phải kiểu tham chiếu , vì vậy đừng mong đợi chúng có ngữ nghĩa tham chiếu trừ khi chúng được đóng hộp thành kiểu tham chiếu. Không có quyền anh ngoài bổ sung.


0

Bạn đang tăng giá trị null ???

int? a = null;
a++;

Câu lệnh này đơn giản có nghĩa null++là null + 1.

Theo tài liệu này, Một kiểu nullable có thể đại diện cho phạm vi giá trị chính xác cho kiểu giá trị cơ bản của nó, cộng thêm một giá trị null khác. có thể được gán giá trị null

Ở đây bạn đang tăng giá trị null, sau đó nó cũng sẽ trở thành giá trị null không phải 0 hoặc bất kỳ số nguyên nào khác.

Tại sao nó in trống thay vì lỗi ??

khi bạn in kiểu nullable với giá trị null nó sẽ in trống thay vì lỗi vì bạn đang in một biến tức là giá trị của vị trí bộ nhớ. có thể null hoặc bất kỳ số nguyên nào.

Nhưng khi bạn cố gắng in null bằng cách sử dụng Console.WriteLine(null), vì null không phải là một biến, vì vậy nó không tham chiếu đến bất kỳ vị trí bộ nhớ nào. Và do đó nó gây ra lỗi "NullReferenceException".

Sau đó, làm thế nào bạn có thể in bất kỳ số nguyên nào bằng cách sử dụng Console.WriteLine(2);??

Trong trường hợp này, 2 sẽ ở trong bộ nhớ tại vị trí tạm thời và con trỏ trỏ đến vị trí bộ nhớ đó để in.

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.