2014-07-24 80 views
7

我想列出不同的對象。我嘗試實現IEqualityComparer,但沒有成功。請如果有人可以查看我的代碼,並給我一些關於IEqualityComparer的解釋。我有以下情況:實施IEqualityComparer

public class Message 
{ 
    public int x { get; set; } 
    public string y { get; set; } 
    public string z { get; set; } 
    public string w { get; set; } 
} 

public class MessageComparer : IEqualityComparer<Message> 
{ 
    public bool Equals(Message x, Message y) 
    { 
     if (Object.ReferenceEquals(x, y)) return true; 

     if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) 
      return false; 
     if (x.x == y.x && x.y == y.y && x.z == y.z && x.w == y.w) 
     { 
      return true; 
     } 
     return false; 
    } 

    public int GetHashCode(Message number) 
    { 
     //if (Object.ReferenceEquals(number, null)) return 0; 
     int hashX = number.x.GetHashCode(); 
     int hashY = number.y == null ? 0 : number.y.GetHashCode(); 
     int hashZ = number.z == null ? 0 : number.z.GetHashCode(); 
     int hashW = number.w == null ? 0 : number.w.GetHashCode(); 

     return hashX^hashY^hashZ^hashW; 

    } 
} 

這是我與留言對象列表:

Message m1 = new Message(); 
     m1.x = 1; 
     m1.y = "A"; 
     m1.z = "B"; 
     m1.w = "C"; 

     Message m2 = new Message(); 
     m2.x = 1; 
     m2.y = "A"; 
     m2.z = "B"; 
     m2.w = "C"; 

     Message m3 = new Message(); 
     m3.x = 1; 
     m3.y = "A"; 
     m3.z = "B"; 
     m3.w = "C"; 

     Message m4 = new Message(); 
     m4.x = 2; 
     m4.y = "A"; 
     m4.z = "B"; 
     m4.w = "C"; 

     Message m5 = new Message(); 
     m5.x = 3; 
     m5.y = "W"; 
     m5.z = "D"; 
     m5.w = "C"; 

     Message m6 = new Message(); 
     m6.x = 4; 
     m6.y = "S"; 
     m6.z = "F"; 
     m6.w = "R"; 

     List<Message> collection = new List<Message>(); 
     collection.Add(m1); 
     collection.Add(m2); 
     collection.Add(m3); 
     collection.Add(m4); 
     collection.Add(m5); 

     collection.Distinct(new MessageComparer()); 

當我打電話在列表中的元素鮮明的()方法的人數相同。 謝謝。

+1

你分配不同調用的結果給一個變量或只是檢查原始列表此鏈接?如果你不分配任何東西,你需要。 'Distinct()'返回一個'IEnumerable'而不是在原地進行更新 – eouw0o83hf

+0

謝謝,你是對的:) – kat1330

回答

11

試試這個:

var distinct = collection.Distinct(new MessageComparer()); 

然後使用distinct爲以後的事情。

看起來你忘記了IEnumerable<>的一成不變的本質。 LINQ方法都沒有改變原來的變量。相反,它們返回包含表達式結果的IEnuerable<T>。例如,讓我們考慮一個簡單的List<string> original,其內容爲{ "a", "a", "b", "c" }

現在,我們打電話original.Add("d");。該方法沒有返回值(它是void)。但是如果我們打印出original的內容,我們會看到{ "a", "a", "b", "c", "d" }

另一方面,現在撥打電話original.Skip(1)。此方法確實有有一個返回值,其中一個類型爲IEnumerable<string>。這是一個LINQ表達式,並且不會對原始集合執行副作用操作。因此,如果我們稱之爲original,我們將看到{ "a", "a", "b", "c", "d" }。但是,該方法的結果將是{ "a", "b", "c", "d" }。正如你所看到的,結果會跳過一個元素。

這是因爲LINQ方法接受IEnumerable<T>作爲參數。因此,他們沒有實施原始列表的概念。你可以通過擴展方法傳遞一個ReadOnlyCollection,他們仍然可以通過它進行評估。因此,他們不能改變原始收藏品,因爲原始收藏品可以用許多方式書寫。

所有這一切,但表中的形式。每行開始與原{ "a", "a", "b", "c" }

Context  Example function Immutable? Returned Value  Collection after calling 
Collection Add("d")   No   (void)    { "a", "a", "b", "c", "d" }: 
LINQ  Skip(1)    Yes   { "a", "b", "c" } { "a, "a", "b", "c" }: 
2

你並不需要實現的IEqualityComparer:

public class Message 
    { 
     protected bool Equals(Message other) 
     { 
      return string.Equals(x, other.x) && string.Equals(y, other.y) && string.Equals(z, other.z) && string.Equals(w, other.w); 
     } 

     public override bool Equals(object obj) 
     { 
      if (ReferenceEquals(null, obj)) return false; 
      if (ReferenceEquals(this, obj)) return true; 
      if (obj.GetType() != this.GetType()) return false; 
      return Equals((Message) obj); 
     } 

     public override int GetHashCode() 
     { 
      unchecked //Ignores overflows that can (should) occur 
      { 
       var hashCode = x; 
       hashCode = (hashCode*397)^(y != null ? y.GetHashCode() : 0); 
       hashCode = (hashCode*397)^(z != null ? z.GetHashCode() : 0); 
       hashCode = (hashCode*397)^(w != null ? w.GetHashCode() : 0); 
       return hashCode; 
      } 
     } 

     public int x { get; set; } 
     public string y { get; set; } 
     public string z { get; set; } 
     public string w { get; set; } 
    } 
+0

取決於案例。如果在特定情況下只需要這種比較,最好使用單獨的比較器。 Overriding Equals方法也會影響其他地方。 –

+0

它以積極的方式影響其他地方,您通常希望將其實施爲像這樣的數據類 –

0

,給予更詳細的信息,這個鏈接

http://dotnetvisio.blogspot.in/2015/12/usage-of-icomparer-icomparable-and.html

的IEqualityComparer是用於查找對象是否爲Equal的接口,現在我們將在需要查找的示例中看到它集合中對象的區別。此接口將實現的方法 的Equals(T OBJ1,T OBJ2)

抽象公共類Person { 公共字符串名字{獲得;組; } public string LastName {get;組; } public string Address {set;得到; }}

public enum SortType 
{ 
    ByID, 
    BySalary 
} 

    public class EmployeeDistinctEquality : IEqualityComparer<Employee> 
    { 
     public EmployeeDistinctEquality() 
     { 

     } 

     public bool Equals(Employee x, Employee y) 
     { 
      if (x == null && x == null) 
       return true; 
      else if (x == null || y == null) 
       return false; 
      else if (x.Id == y.Id) 
       return true; 
      else 
       return false; 
     } 

     public int GetHashCode(Employee obj) 
     { 
      return obj.Id.GetHashCode(); 
     } 
    } 

請參閱瞭解更多詳細信息

http://dotnetvisio.blogspot.in/2015/12/usage-of-icomparer-icomparable-and.html