2010-10-03 54 views
2

所以我有一個類重寫Equals(object obj)和GetHashCode()以及實現IEquatable。爲了使這種類型的工作在檢查平等時更自然一些,我認爲,嘿,我會超負荷平等運算符和不平等運算符,無後顧之憂......重載的操作符參數始終爲空

呃哦,憂慮...考慮以下 - 其中兩個實例的myType不爲空:

if (myType != container.myType) //NullReferenceException 
{ 
    //never get here 
} 
//never get here either 

現在,容器是另一個類以保存其中用於緩存項以外的東西的的myType一個實例。

下面是對的myType實際的(相關)代碼:

public class MyType : IEquatable<MyType> 
{ 
    public static bool operator ==(MyType myTypeA, MyType myTypeB) 
    { 
     return myTypeA.Equals(myTypeB); 
    } 

    public static bool operator !=(MyType myTypeA, MyType myTypeB) 
    { 
     return !(myTypeA == myTypeB); 
    } 

    public override bool Equals(object obj) 
    { 
     if (obj != null && obj is MyType) 
     { 
      return Equals((MyType)obj); 
     } 
     return false; 
    } 

    public bool Equals(MyType other) 
    { 
     if (other != null) 
     { 
      return other.ToString() == ToString(); 
     } 
     return false; 
    } 
} 

在這方面的經驗嗎?

謝謝。

+0

你能後的堆棧跟蹤?因爲如果你得到一個NRE,東西必須是空的。你是如何驗證這兩個參數都不爲空的? – 2010-10-03 15:10:50

回答

2

棘手的......問題是,你使用等號平等覆蓋內部如下:

public bool Equals(MyType other) 
{ 
    if (other != null) 

它去你重載=操作符,這反過來去你的==操作符! ,它試圖做null.Equals ...

+0

這是一個常見的錯誤。或者使用'object.ReferenceEquals'或者'if((object)other!=(object)null){...}'將操作數(或者其中的一個)這是靜態的(因此從未被覆蓋)。 – 2013-07-24 08:24:33

3

兩個指針 -

  1. 如果您已經撤消了對類==!=,確保使用ReferenceEquals檢查在過載實現中爲null,而不是==,因爲這會調用您的重載操作符並進入循環或試圖在空this引用上調用Equals,這可能是在這裏發生的事情。
  2. 請勿覆蓋類別上的==!=。這些運營商是爲價值平等而設計的,而類別的設計並非真正具有價值平等。要麼刪除操作員重載,要麼使結構成爲一個結構。
+0

謝謝,這樣,並且在不遺漏調用的情況下逐步執行代碼時的一點耐心,讓我意識到Equals實際上被調用爲null作爲導致使用null調用相等運算符的比較,導致另一個等於null的呼叫,這導致另一個帶有兩個空值的平等運算符呼叫,以及BANG。可能會更糟糕,可能會有一個可怕的循環。 – 2010-10-03 16:30:58

1

正如其他人已經聲明,你需要仔細檢查空值,因爲它會再次調用你的相等函數,通常導致StackOverflowException。

當我使用IEquatable接口類我通常使用下面的代碼:

public override bool Equals(object obj) 
{ 
    // If obj isn't MyType then 'as' will pass in null 
    return this.Equals(obj as MyType); 
} 

public bool Equals(MyType other) 
{ 
    if (object.ReferenceEquals(other, null)) 
    { 
     return false; 
    } 

    // Actual comparison code here 
    return other.ToString() == this.ToString(); 
}