2017-08-09 43 views
1

我試圖寫一個相等比較的簡單類3場,就像這樣:當等式比較器基於OR操作時,編寫GetHashCode()的正確方法是什麼?

public class NumberClass 
{ 
    public int A { get; set; } 
    public int B { get; set; } 
    public int C { get; set; } 
} 

我爲NumberClass兩個對象的條件是相等的,如果Obj1.A == Obj2.A || Obj1.B == Obj2.B(換句話說,OR), Obj1和Obj2是NumberClass的實例。

我可以很容易地寫我的比較器的Equals()如下,但我不知道如何處理我的GetHashCode()方法做。

public bool Equals(NumberClass x, NumberClass y) 
{ 
    if (x.A == y.A || x.B == y.B) 
     return true; 
    else 
     return false; 
} 

public int GetHashCode(NumberClass obj) 
{ 
    return ??? 
} 

如果我的平等條件是和代替或者,我可以寫我GetHashCode()如下,taken from this SO answer

public int GetHashCode(NumberClass obj) 
{ 
    unchecked 
    { 
     int hash = 17; 
     if (obj != null) 
     { 
      hash = hash * 23 + obj.A.GetHashCode(); 
      hash = hash * 23 + obj.B.GetHashCode(); 
     } 
     return hash; 
    } 
} 

但這顯然不會支持或因爲只有AB相等的一個工作就足夠了我平等的條件是真實的。

一個解決辦法,我能想到的總是返回在GetHashCode()相同的值就足以LINQ操作,如Distinct(),但我覺得應該有另一種方式爲有自身的缺點。

什麼是處理這種情況的正確方法?

P.S. 爲了測試,想象我的main()函數如下:

static void Main(string[] args) 
{ 
    List<NumberClass> list = new List<NumberClass>(); 
    list.Add(new NumberClass { A = 1, B = 2, C = 3 }); 
    list.Add(new NumberClass { A = 1, B = 22, C = 33 }); 

    var distinct = list.Distinct(new NumberComparer()); 
    Console.ReadKey(); 
} 

我希望distinct僅包含在列表中的第一個元素。

回答

4

有適合您的情況無解。你的對象違反了平等比較器工作所必需的假設,例如,它假定平等將是傳遞性的,但這不是平等的實現。

你根本就無法使用任何基於散列的算法,只要你有這樣的「模糊」的平等。

+0

能否請您解釋一下你的_it意思假定平等將是transitive_? – Sach

+1

@Sach如果A等於B,B等於C,那麼A等於C(如果等於傳遞)。你的情況並非如此。 – Servy

+0

明白了,謝謝! 好吧,我想在這種情況下唯一的解決方法是在'GetHashCode()'中返回相同的值,或者根本不使用比較器並進行舊學校比較。 – Sach

相關問題