2013-05-21 8 views
10

ich einen Fall, wo ich ein paar Punkte auf verschiedene greifen müssen, aber meine Quelle ist eine Sammlung von Objekten mit zwei Eigenschaften, wie folgt aus:Implementierung IEqualityComparer <T> auf ein Objekt mit zwei Eigenschaften in C#

public class SkillRequirement 
{ 
    public string Skill { get; set; } 
    public string Requirement { get; set; } 
} 

ich versuche, eine Sammlung zu erhalten, wie folgt:

SkillRequirementComparer sCom = new SkillRequirementComparer(); 

var distinct_list = source.Distinct(sCom); 

ich habe versucht, eine IEqualityComparer<T> dafür zu implementieren, aber ich fiel am GetHashCode() Methode stapfte.

Die Klasse für die Comparer:

public class SkillRequirementComparer : IEqualityComparer<SkillRequirement> 
{ 
    public bool Equals(SkillRequirement x, SkillRequirement y) 
    { 
     if (x.Skill.Equals(y.Skill) && x.Requirement.Equals(y.Requirement)) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 

    public int GetHashCode(SkillRequirement obj) 
    { 
     //????? 
    } 
} 

Normalerweise würde ich GetHashCode() auf einer Eigenschaft nur, sondern weil ich zwei Eigenschaften bin im Vergleich zu, ich bin ein bisschen mit einem Verlust von dem, was zu tun ist. Mache ich etwas falsch oder vermisse etwas wirklich Offensichtliches?

+0

Seien Sie vorsichtig, wenn Sie einen 'GetHashCode()' verwenden, der von veränderbaren Feldern abgeleitet ist! Wenn Sie das Objekt in eine Hashing-Sammlung einfügen, ändern Sie eines der Felder - autsch. Ich schlage vor, es unveränderlich zu machen. –

+0

Die Werte für die Eigenschaften stammen ursprünglich aus einer Datenbank, wo die Spalten Nullen nicht zulassen, es gibt auch Prüfungen auf Null oder leere Zeichenfolgen, bevor ein Objekt der Quellenliste hinzugefügt wird, also ist es kein Problem: ^) –

Antwort

10

Sie können GetHashCode in der folgenden Art und Weise implementieren:

public int GetHashCode(SkillRequirement obj) 
{ 
    unchecked 
    { 
     int hash = 17; 
     hash = hash * 23 + obj.Skill.GetHashCode(); 
     hash = hash * 23 + obj.Requirement.GetHashCode(); 
     return hash; 
    } 
} 

originally von J.Skeet

Wenn die Eigenschaften sein können null Sie eine NullReferenceException vermeiden sollten, zB:

int hash = 17; 
hash = hash * 23 + (obj.Skill ?? "").GetHashCode(); 
hash = hash * 23 + (obj.Requirement ?? "").GetHashCode(); 
return hash; 
+1

(Eigentlich stammt es ursprünglich von Josh Bloch;) –

+0

Keine gute Idee. Diese Eigenschaften sind veränderbar. –

+0

@ UfukHacıoğulları: Können Sie Ihre Einwände angeben? –

1

Ich möchte die folgende Stapelüberlaufposition verknüpfen Auch ts wenn die Frage schon beantwortet ..

GetHashCode -

Why is it important to override GetHashCode when Equals method is overridden?

Auch in der obigen Antwort Tim Schmelter sagt the properties can be null you should avoid a NullReferenceException

int hash = 17; 
hash = hash * 23 + (obj.Skill ?? "").GetHashCode(); 
hash = hash * 23 + (obj.Requirement ?? "").GetHashCode(); 
return hash; 

IEqualityComparer -

  1. What is the difference between using IEqualityComparer and Equals/GethashCode Override
  2. What's the role of GetHashCode in the IEqualityComparer in .NET?
  3. How and when to use IEqualityComparer in C#

IEquatable - What's the difference between IEquatable and just overriding Object.Equals()?

Equals - Guidelines for Overloading Equals()

class TwoDPoint : System.Object 
{ 
    public readonly int x, y; 

    public TwoDPoint(int x, int y) //constructor 
    { 
     this.x = x; 
     this.y = y; 
    } 

    public override bool Equals(System.Object obj) 
    { 
     // If parameter is null return false. 
     if (obj == null) 
     { 
      return false; 
     } 

     // If parameter cannot be cast to Point return false. 
     TwoDPoint p = obj as TwoDPoint; 
     if ((System.Object)p == null) 
     { 
      return false; 
     } 

     // Return true if the fields match: 
     return (x == p.x) && (y == p.y); 
    } 

    public bool Equals(TwoDPoint p) 
    { 
     // If parameter is null return false: 
     if ((object)p == null) 
     { 
      return false; 
     } 

     // Return true if the fields match: 
     return (x == p.x) && (y == p.y); 
    } 

    public override int GetHashCode() 
    { 
     //return x^y; 
    } 
}