2011-01-24 63 views
7

所以我試圖做這個工作,我似乎無法知道它爲什麼不起作用linq&distinct,執行equals&gethashcode

演示代碼;

namespace ConsoleApplication1 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     var myVar = new List<parent >(); 
     myVar.Add(new parent() { id = "id1", blah1 = "blah1", c1 = new child() { blah2 = "blah2", blah3 = "blah3" } }); 
     myVar.Add(new parent() { id = "id1", blah1 = "blah1", c1 = new child() { blah2 = "blah2", blah3 = "blah3" } }); 

     var test = myVar.Distinct(); 

     Console.ReadKey(); 

    } 
} 


public class parent : IEquatable<parent> 
{ 
    public String id { get;set;} 
    public String blah1 { get; set; } 
    public child c1 { get; set; } 

    public override int GetHashCode() 
    { 
     unchecked // Overflow is fine, just wrap 
     { 
      int hash = 17; 
      // Suitable nullity checks etc, of course :) 
      hash = hash * 23 + id.GetHashCode(); 
      hash = hash * 23 + blah1.GetHashCode(); 
      hash = hash * 23 + (c1 == null ? 0 : c1.GetHashCode()); 
      return hash; 
     } 
    } 

    public bool Equals(parent other) 
    { 
     return object.Equals(id, other.id) && 
      object.Equals(blah1, other.blah1) && 
      object.Equals(c1, other.c1); 
    } 

} 

public class child : IEquatable<child> 
{ 
    public String blah2 { get; set; } 
    public String blah3 { get; set; } 

    public override int GetHashCode() 
    { 
     unchecked // Overflow is fine, just wrap 
     { 
      int hash = 17; 
      // Suitable nullity checks etc, of course :) 
      hash = hash * 23 + blah2.GetHashCode(); 
      hash = hash * 23 + blah3.GetHashCode(); 
      return hash; 
     } 
    } 

    public bool Equals(child other) 
    { 
     return object.Equals(blah2, other.blah2) && 
      object.Equals(blah3, other.blah3); 
    } 

} 
} 

任何人都可以發現我的錯誤?

+4

+1爲一個完整的例子。 – SLaks 2011-01-24 20:42:29

+1

你有什麼錯誤?什麼是預期的行爲?執行你的代碼只是顯示沒有任何內容,並在按下某個鍵時退出。 – jdmichal 2011-01-24 20:44:35

+0

@jdmichal,在控制檯上放置一個斷點。讀取鍵並查看測試變量,應該說count = 1而不是2 – Fredou 2011-01-24 20:45:44

回答

5

你需要重寫Equals(object)方法:

public override bool Equals(object obj) { 
    return Equals(obj as parent); 
} 

object.Equals方法(不像EqualityComparer<T>.Default)不使用IEquatable接口。因此,當您編寫object.Equals(c1, other.c1)時,它不會調用您的Child.Equals(Child)方法。

你並不是絕對需要爲parent那樣做,但是你的真的應該是

0

當添加計算,你可能想嘗試像

hash ^= id.GetHashCode();

不知道的東西,如果這是什麼原因造成您的問題哈希值。

3

無論你做什麼SLaks建議,或者你使用EqualityComparer<child>.Defaultparent類使用IEquatable<child>實現:

public bool Equals(parent other) 
    { 
    return object.Equals(id, other.id) && 
    object.Equals(blah1, other.blah1) && 
    EqualityComparer<child>.Default.Equals(c1, other.c1); 
} 
0

有幾件事情讓這裏。如果我要在諸如GetHashCode的類中實現任何平等的方面,覆蓋==或IEquatable,我總是使用以下模式。

  1. 重載equals
  2. 重寫GetHashCode
  3. 實施IEquatable<T>這意味着實施Equals(T)
  4. 實現!=

所以實現==,如果我有一個名爲ExpiryMonth帶班屬性年和月,這是實現的外觀。現在適應其他類型的課程是一項相當愚蠢的任務。

我已經基於這種模式在其他幾個stackoverflow答案,這都是值得信貸,但我一直沒有跟蹤。

通過始終將所有這些元素實現在一起,它確保在包括字典和Linq操作在內的各種環境中進行適當的等式操作。

public static bool operator !=(ExpiryMonth em1, ExpiryMonth em2) 
    { 
     if (((object)em1) == null || ((object)em2) == null) 
     { 
      return !Object.Equals(em1, em2); 
     } 
     else 
     { 
      return !(em1.Equals(em2)); 
     } 
    } 
    public static bool operator ==(ExpiryMonth em1, ExpiryMonth em2) 
    { 
     if (((object)em1) == null || ((object)em2) == null) 
     { 
      return Object.Equals(em1, em2); 
     } 
     else 
     { 
      return em1.Equals(em2); 
     } 
    } 
    public bool Equals(ExpiryMonth other) 
    { 
     if (other == null) { return false; } 
     return Year == other.Year && Month == other.Month; 
    } 
    public override bool Equals(object obj) 
    { 
     if (obj == null) { return false; } 
     ExpiryMonth em = obj as ExpiryMonth; 
     if (em == null) { return false; } 
     else { return Equals(em); } 
    } 
    public override int GetHashCode() 
    { 
     unchecked // Overflow is not a problem 
     { 
      var result = 17; 
      result = (result * 397) + Year.GetHashCode(); 
      result = (result * 397) + Month.GetHashCode(); 
      return result; 
     } 
    } 
相關問題