2012-04-16 65 views
6

可能重複:
Why check this != null?爲什麼String.Equals(Object obj)檢查這個== null?

// Determines whether two strings match. 
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 
public override bool Equals(Object obj) 
{ 
    //this is necessary to guard against reverse-pinvokes and 
    //other callers who do not use the callvirt instruction 
    if (this == null) 
     throw new NullReferenceException(); 

    String str = obj as String; 
    if (str == null) 
     return false; 

    if (Object.ReferenceEquals(this, obj)) 
     return true; 

    return EqualsHelper(this, str); 
} 

我不明白的是,它正在檢查當前實例,this,對空的事實。評論有點混亂,所以我想知道那個評論究竟意味着什麼?

任何人都可以舉一個例子,說明如果這個檢查不存在,這是否意味着我也應該把這個檢查放在我的課程中?

+0

@FlorianGreinacher:不是可能的重複,但幾乎是一個確切的重複,哈哈。我想知道爲什麼當我寫我的問題時,它沒有出現在「相關」中? – 2012-04-17 01:18:56

回答

6

該檢查是否存在針對本機代碼的警惕,該代碼可能會使用空值this指針調用函數。這在C#中不會發生,因此您不必在代碼中放置類似的警衛。在C#完成之前編寫String類很有可能,作者可能認爲防止出現空值很重要,或者從本地代碼和其他可以方便地調用null方法的地方調用String方法很常見。

請注意,即使您設法使用空值this進行調用,並且您沒有警惕,但所發生的一切就是該例外情況會有所不同。它可能是一個不同的例外,它可能會被不同的成員拋出,但否則不太可能有所作爲。

換句話說,如果空檢查不存在,EqualsHelper(或其一個被調用者)將拋出異常而不是Equals。由於希望隱藏用戶可見函數的內部結構,因此將檢查權放在開頭是很有意義的。

2
  • 類似C#和VB.NET的語言在輸入實例方法之前使用callvirt來拋出NullReference(this == null)檢查是不必要的。
  • F#和Managed C++(大部分時間)等語言都使用call指令,您可以使用該指針爲null的實例方法。 (this == null)確實有效果。

添加的空檢查不僅僅適用於後者的語言,而且還用於幫助調試拋出錯誤(調用空對象的實例方法)的位置。如果它不在那裏,只要這不是取消引用(訪問成員變量),就可以在類中調用任何方法而不會出現任何錯誤。這可以走得太遠,以至於你的空對象有幾個方法調用確實有效,並且突然間你得到一個空引用異常(訪問實例數據的方法)。

如果你看看.NET類中的檢查,很明顯只有像string這樣的一些顯着的類才包含這樣的警衛。像IndexOf這樣的其他方法並沒有防範這一點。這是不一致的,但我認爲這種雙空檢查的性能損失是不值得的,因爲BCL的大多數用戶都是使用callvirt指令的語言,而第二個空檢查沒有幫助。

+1

在F#中,'let x =「a」。等於(「b」)仍然編譯爲「callvirt」 – colinfang 2013-07-10 19:18:48

相關問題