Tại sao toán tử trả về false khi được null?


135

Dường như với tôi rằng các isnhà điều hành là một chút không phù hợp.

bool Test()
{
    // Returns false, but should return true.
    return null is string;
}

Người ta kỳ vọng rằng nullgiá trị thuộc về bất kỳ loại tham chiếu (hoặc nullable) nào. Và thực tế, đặc tả ngôn ngữ C # nói điều gì đó hỗ trợ cho giả thuyết này, ví dụ (6.1.6 Chuyển đổi tham chiếu ngầm):

Các chuyển đổi tham chiếu ngầm là:
...
• Từ chữ không thành bất kỳ kiểu tham chiếu nào.

Mô tả (7.10.10 là nhà điều hành) của các isnhà khai thác bắt đầu bằng cách nói rằng biểu thức (E is T)sẽ cho kết quả đúng khi chuyển đổi tài liệu tham khảo từ Eđể Ttồn tại, nhưng sau đó các tác giả đi vào bằng cách loại trừ một cách rõ ràng trường hợp khi Enullđen hoặc có nullgiá trị .

Tại sao họ làm điều đó? Đối với tôi nó có vẻ phản trực giác.


Tại sao họ loại trừ rõ ràng null là câu hỏi tốt nhất cho các lập trình
viên.stackoverflow.com

2
Tôi không thể hủy bỏ phiếu bầu chặt chẽ của mình, nhưng những câu hỏi này vẫn ổn ở đây: meta.stackexchange.com/questions / 388/50
Merlyn Morgan-Graham

trong java null typeof Objectcũng trả về false
ratchet freak

Giả sử rằng null is stringtrue, và điều này có nghĩa rằng nulllà một string. Cũng cho rằng đó null is Nullable<int>true, ngụ ý đó nulllà a Nullable<int>. Bây giờ, trả lời câu hỏi này: thuộc loại nullnào?
CVn

1
@Michael Kjorling: Không sequitur. Từ các sự kiện được đề cập (null là một chuỗi, null là Nullable <int>), nó không tuân theo việc tôi có thể trả lời câu hỏi đó.
Gebb

Câu trả lời:


195

Câu hỏi này là chủ đề của blog của tôi vào ngày 30 tháng 5 năm 2013 . Cảm ơn vì câu hỏi tuyệt vời của bạn!


Bạn đang nhìn chằm chằm vào một đường lái xe trống.

Có người hỏi bạn "đường lái xe của bạn có thể giữ một chiếc Honda Civic không?"

Đúng. Có nó có thể.

Ai đó chỉ bạn ở một đường lái xe thứ hai. Nó cũng trống rỗng. Họ hỏi "Nội dung hiện tại của đường lái xe của tôi có vừa với đường lái xe của bạn không?"

Vâng, rõ ràng. Cả hai đường lái xe đều trống! Vì vậy, rõ ràng nội dung của một trong những có thể phù hợp với nhau, bởi vì không có nội dung của một trong hai ở nơi đầu tiên.

Có người hỏi bạn "Đường lái xe của bạn có chứa một chiếc Honda Civic không?"

Không nó không.

Bạn đang nghĩ rằng istoán tử trả lời câu hỏi thứ hai: được đưa ra giá trị này, nó có phù hợp với một biến của loại đó không? Có một tham chiếu null phù hợp với một biến của loại này? Có nó làm.

Đó không phải là câu hỏi mà người isvận hành trả lời. Câu hỏi mà người isvận hành trả lời là câu hỏi thứ ba. y is Xkhông yêu cầu " ymột giá trị pháp lý của một biến kiểu X? " nó hỏi " có phải là ymột tài liệu tham khảo có giá trị cho một đối tượng của loại hình X? " Kể từ khi một tham chiếu null không phải là một tài liệu tham khảo có giá trị cho bất kỳ đối tượng của bất kỳ loại, câu trả lời là "không ". Đường lái xe đó trống rỗng; Nó không chứa một chiếc Honda Civic.

Một cách khác để xem xét đó là y is Xtrả lời câu hỏi "nếu tôi nói y as X, tôi có nhận được kết quả không null không? Nếu y là null, rõ ràng câu trả lời là không!


Để nhìn sâu hơn một chút vào câu hỏi của bạn:

Người ta kỳ vọng rằng giá trị null thuộc về bất kỳ loại tham chiếu (hoặc nullable) nào

Người ta sẽ mặc nhiên cho rằng một loại là một tập hợp các giá trịkhả năng tương thích gán của một giá trị y với một biến loại X không có gì khác hơn là kiểm tra xem y có phải là thành viên của tập x không .

Mặc dù đó là một cách cực kỳ phổ biến để xem xét các loại, nhưng đó không phải là cách duy nhất để xem các loại và đó không phải là cách mà C # nhìn vào các loại. Tài liệu tham khảo Null là thành viên không có loại trong C #; khả năng tương thích nhượng được không chỉ đơn thuần là kiểm tra một tập để xem nếu nó chứa một giá trị. Chỉ vì tham chiếu null tương thích gán với biến của loại tham chiếu X không có nghĩa là null là thành viên của loại X. Quan hệ "được gán tương thích với" và quan hệ "là thành viên của loại" rõ ràng có rất nhiều chồng chéo, nhưng chúng không giống nhau trong CLR.

Nếu suy nghĩ về lý thuyết loại bạn quan tâm, hãy xem các bài viết gần đây của tôi về chủ đề này:

Cái mà bạn gọi là "loại" là gì? Phần một

Cái mà bạn gọi là "loại" là gì? Phần hai


@Gebb: Rất vui được giúp đỡ. Bài viết này cũng có thể được bạn quan tâm: blog.msdn.com/b/ericlippert/archive/2010/09/16/ mẹo
Eric Lippert

Eric đã biến bài viết này thành một bài đăng trên blog: ericlippert.com/2013/05/30/what-the-meaning-of-is-is
Kevin Cathcart

y is Xkhông hỏi "là ymột giá trị pháp lý của một biến loại X?" Nó hỏi "Là ymột tham chiếu hợp lệ cho một đối tượng của loại X?" Đó là toàn bộ điểm! cảm ơn!
Jalal

Nhưng nếu tôi hỏi y is int?, thì tôi sẽ hỏi "Đường lái xe của bạn có chứa một chiếc Honda Civic hay không?". Tại sao câu trả lời vẫn là không khi đường lái xe của bạn trống? Nếu bạn nhìn dưới mui xe, nó chỉ trở nên tồi tệ hơn, vì câu hỏi trở thành "Đường lái xe của bạn có chứa một chiếc Honda Civic hay một biển báo 'Không có Honda Civic ở đây'?". Ngay cả khi đường lái xe của bạn có dấu hiệu đã nói, câu trả lời vẫn là không.
Fax

1
@Gerard: Khi tôi đưa ra những câu trả lời dài dòng, dài dòng, mọi người nói với tôi rằng chúng nên ngắn hơn, và khi tôi đưa ra những câu trả lời ngắn gọn, ngắn gọn, mọi người sẽ nói với tôi rằng chúng nên dài hơn. Kết luận của tôi là: mọi người thích phàn nàn. Vì bạn có cảm giác về điều gì tạo ra câu trả lời hay cho câu hỏi tám tuổi này, nên tôi đề nghị bạn chỉ cho chúng tôi điều gì tạo ra câu trả lời hay bằng cách tự trả lời, để chúng ta có thể học hỏi.
Eric Lippert

24

Tôi nghĩ null is stringtrả lại sai là rất trực quan. Null có nghĩa là không có gì, và nó chắc chắn không phải là một chuỗi. Vì vậy, nó sẽ trả lại sai. Mặc dù đó là một sự lựa chọn mà các nhà thiết kế ngôn ngữ đưa ra, nhưng nó là một lựa chọn rất trực quan khi bạn xem xét ý nghĩa của thế giới thực là null.


2
+1 vì câu hỏi thực sự là về việc nó có trực quan hay không và không đặt câu hỏi về thông số kỹ thuật mà OP đã biết. Nếu bạn hỏi nó như một câu tiếng Anh "là nullmột chuỗi" thì câu trả lời là không, nó không phải, nó khác với "có thể nullgán cho string"
Davy8

null is stringlà khá trực quan, (string)null is stringcó thể yêu cầu tạm dừng nếu bạn không thực sự quen thuộc với cách thức tham chiếu null hoạt động trong C #.
decPL

24

Nghĩa nullđen có thể được gán cho bất kỳ loại tham chiếu. Nó không phải là một loại trong chính nó. Đó là một đặc biệt theo nghĩa đenđại diện cho một tham chiếu null.

Trong trường hợp issẽ trở lại truekhi một nullsẽ được thông qua, bạn sẽ có thể làm gì với nullnghĩa đen? Không có gì - nó là null. Điều gì sẽ là điểm của nó trở lại truengoại trừ các vấn đề khó hiểu?


Bất kể - về mặt trực quan như thế nào, hãy đọc mã bằng tiếng Anh và cho tôi biết:

null is string;

Khi tôi thấy điều đó, nó dường như đang đặt câu hỏi is "nothing" a string?. Trực giác của tôi nói với tôi rằng không, không phải - nó nothing.


Điều đó ổn, nhưng sau đó nó cũng là một chuỗi, phải không? Nhưng tại sao (null is string)trở lại flase sau đó?
Gebb

Tôi đã phrased nó theo cách khác vòng. Bất kỳ loại tham chiếu có thể là null. null chỉ là null.
Đánh dấu H

@Oded vậy giá trị null có phải là giá trị hợp lệ của loại đối tượng không? Tôi có thể gán nó cho một biến của loại này, phải không? Vì vậy, câu trả lời dường như là có, giá trị này hoàn toàn hợp lệ và tôi đoán là (null is object)biểu thức cần kiểm tra chính xác điều đó.
Gebb

@Gebb: Đừng quên rằng ValueTypes cũng là đối tượng, nhưng không phải là kiểu tham chiếu.
Đánh dấu H

1
@Oded: "Điều gì sẽ trở thành sự thật, ngoại trừ những vấn đề khó hiểu?" Trên thực tế, nó sẽ làm cho ngôn ngữ hợp lý hơn. Hãy xem xét hai điểm sau: (1) isnhà điều hành kiểm tra xem có tham chiếu (chúng tôi không cần các loại chuyển đổi khác ở đây) không; (2) nullcó thể được chuyển đổi thành bất kỳ loại tham chiếu. Do đó (null is T), trong đó T là loại tham chiếu nên trả về true. Nhưng không, ở đây chúng ta có ngoại lệ rõ ràng đó, đó là điều có vẻ khó hiểu với tôi.
Gebb

12

http://msdn.microsoft.com/en-us/l Library / scekt9xw% 28v = vs.71% 29.aspx

An là biểu thức ước lượng là đúng nếu cả hai điều kiện sau được đáp ứng:

  • biểu thức không phải là null.
  • biểu thức có thể được đúc để gõ. Nghĩa là, một biểu thức truyền của biểu mẫu (loại (biểu thức) sẽ hoàn thành mà không đưa ra một ngoại lệ. Để biết thêm thông tin, hãy xem 7.6.6 Biểu thức truyền.

1
Dù sao, tài liệu chỉ nói rằng biểu thức không thể là null (mà chúng ta đã biết), nhưng nó không cho biết lý do
tên người dùng

Tại sao bạn muốn nó theo bất kỳ cách nào khác?
Biến khốn khổ

1
@username: Câu trả lời này giải thích cách nó hoạt động một cách máy móc và trích dẫn một tài liệu tham khảo, cung cấp cho bạn một mô hình để làm việc. Bạn đang hỏi ý nghĩa của vũ trụ ở đây. Tôi đoán bạn may mắn vì thần của chúng tôi thường xuyên SO;)
Merlyn Morgan-Graham

10

Như một vấn đề thực tế, có "null là T == false" giúp tôi nhập thêm mã:

Thay vì phải nói

if (X != null && X is Foo) {}

Tôi chỉ có thể nói

if (X is Foo) {}

và được thực hiện với nó.


8

các nullgiá trị

Tôi đã trích dẫn điều này từ câu hỏi của bạn bởi vì nó dường như đi vào trọng tâm của vấn đề. null không phải là một giá trị - đó là sự thiếu vắng của một giá trị. Mục đích của istôi dường như là để trả lời câu hỏi:

Nếu tôi đúc EđểT , tôi sẽ thành công có được một T?

Bây giờ, trong khi bạn có thể đúc nullđến T mà không có lỗi , sau khi làm như vậy bạn không "có T" - không có gì bạn vẫn có. Vì vậy, không phải là null"là" a T, vì vậy istrả về sai.


3

Trong Java có một toán tử thực hiện chính xác điều tương tự, nhưng nó có tên dài hơn nhiều : instanceof. Nó rất trực quan ở đó null instanceof Stringtrả về false, bởi vì null không phải là một ví dụ của bất cứ điều gì, ít hơn nhiều a String. Vì vậy, khi sử dụngnull phiên bản của Java trực quan hơn một chút.

Tuy nhiên, cả hai toán tử này đều trả về true khi được yêu cầu xem qua toàn bộ phân cấp. Ví dụ. nếu ví dụ Stringlà một Object. Và ở đây, Java ít trực quan hơn (vì một thực thể có một loại, rất cụ thể) và C # istrực quan hơn (vì mỗi cái String mộtObject bên trong sâu).

Điểm mấu chốt: nếu bạn cố gắng mô tả logic khá tiên tiến trong một từ, bạn chắc chắn sẽ có ít người nhầm lẫn, theo cách này hay cách khác. Dường như hầu hết mọi người đồng ý về một nghĩa và những người không đồng ý, phải điều chỉnh.

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.