簡體   English   中英

給定null時,為什么is運算符返回false?

[英]Why does the is operator return false when given null?

在我看來, is運算符有點不一致。

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

一個人期望null值屬於任何引用(或可空)類型。 事實上,C#語言規范說明了支持這種假設的東西,例如(6.1.6隱式引用轉換):

隱式引用轉換是:
...
•從null文字到任何引用類型。

說明(7.10.10 is運算符)的is通過說表達式運算符開始(E is T)將導致真正的當從引用轉換ET存在,但隨后筆者通過明確排除的情況下繼續當Enull文字或具有null值時。

他們為什么這樣做? 這對我來說似乎違反直覺。

這個問題是我2013年5月30日博客主題 謝謝你這個好問題!


你正盯着一條空車道。

有人問你“你的車道可以裝一輛本田思域嗎?”

是。 是的,它可以。

有人指着你在第二個車道。 它也是空的。 他們問:“我的車道的當前內容能否適合您的車道?”

是的,很明顯。 兩條車道都是空的! 很明顯,一個人的內容可以適合另一個,因為首先沒有任何內容。

有人問你“你的車道是否包含一輛本田思域?”

不,不是的。

您認為is運算符回答了第二個問題: 給定此值,它是否適合該類型的變量? null引用是否適合此類型的變量? 是的,它確實。

這不是問題的is運營商的答案。 現在的問題是, is運營商的答案是第三個問題。 y is X不問“ y類型的變量的合法值X ?”這問“ y至類型的對象的有效引用X ?”由於空引用不是任何 任何對象的有效引用類型,答案是“不”。 那條車道是空的; 它不包含本田思域。

另一種看待它的方法是y is X回答問題“如果我說y as X ,我會得到非空結果嗎?如果y為空,顯然答案是否定的!


要更深入地了解您的問題:

一個人期望null值屬於任何引用(或可空)類型

可以隱含地假設類型是一組值 ,並且值y與類型X的變量的賦值兼容性僅僅是檢查y是否是集合x的成員

雖然這是查看類型的一種非常常見的方式,但這不是查看類型的唯一方法,而且它不是C#查看類型的方式。 空引用是C#中沒有類型的成員; 分配兼容性 不僅僅檢查組,看它是否包含一個值。 僅僅因為null引用是賦值與引用類型X的變量兼容並不意味着null是X類型的成員。“賦值與”關系兼容並且“是類型的成員”關系顯然有很多重疊,但它們在CLR中不相同。

如果關於類型理論的思考對你感興趣,請查看我最近關於這個主題的文章:

你稱之為“類型”的東西是什么? 第一部分

你稱之為“類型”的東西是什么? 第二部分

可以將null文本分配給任何引用類型。 它本身並不是一種類型。 它是一個特殊的文字表示空引用。

在這種情況下is將返回truenull將被傳遞中,你將能夠用做null的文字? 沒什么 - 它是null 除了令人困惑的事情之外,它會回歸true的重點是什么?


無論如何 - 就直觀性而言,請閱讀英文代碼並告訴我:

null is string;

當我看到它時,它似乎在問這個問題is "nothing" a string? 我的直覺告訴我,不,它不是 - 它nothing

我認為null is string返回false是非常直觀的。 Null意味着什么,它絕對不是一個字符串。 所以它應該返回false。 雖然它是語言設計者的選擇,但當你考慮null的真實世界意義時,它是一個非常直觀的選擇。

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

如果滿足以下兩個條件,則表達式的計算結果為true:

  • 表達式不為空。
  • 表達式可以轉換為類型。 也就是說,表單的類型(表達式)將在不拋出異常的情況下完成。有關更多信息,請參閱7.6.6 Cast表達式。

實際上,“null是T == false”可以節省我輸入額外的代碼:

而不是說

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

我可以說

if (X is Foo) {}

並完成它。

null

我從你的問題中引用了這個,因為它似乎觸及了問題的核心。 null 不是值 - 它是缺少值。 的目的is對我似乎是回答這個問題:

如果我把E投到T ,我會成功獲得T嗎?

現在,雖然你可以毫無錯誤地將nullT 這樣做之后你就不會 “有一個T ” - 你仍然沒有任何東西。 所以它不是的情況下null “是” T ,所以is返回false。

在Java中,有一個運算符執行完全相同的操作,但它具有更長的名稱: instanceof 在那里, null instanceof String返回false是非常直觀的,因為null不是任何東西的實例,更不是String 因此,當使用null ,Java的版本更直觀一些。

但是,當要求查看整個層次結構時,這兩個運算符都返回true。 例如。 如果String實例是Object 這里,它的Java這是不太直觀的(因為一個實例實際上有一個非常特殊類型)和C#的is更直觀的(因為每一個String 一個Object內心深處)。

一句話:如果你試圖用一個詞來描述非常高級的邏輯,那么你很少會有這樣或那樣的人混淆。 似乎大多數人都同意一個意思而那些不同意的人不得不進行調整。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM