2016-06-27 12 views
0

ich die folgende Klasse haben:definieren Gleichheit basierend auf Klasseneigenschaft in HashSet verwendet werden

public class OrderRule { 
    public OrderDirection Direction { get; set; } 
    public String Property { get; set; } 
} 

und ein HashSet davon:

HashSet<OrderRule> rules = // ... 

ich OrderRules müssen gleich betrachtet werden, wenn die Eigenschaft ist gleich.

Wie kann ich das tun?

+0

Sie müssen Equals und GetHashCode Methoden implementieren –

+1

Was verhindert, dass Sie es in der Weise implementieren, die Sie erwähnt haben? –

+0

@TimSchmelter Wenn ich zwei OrderRules mit gleicher Eigenschaft aber unterschiedlicher Richtung hinzufüge, muss ich beide noch als gleich betrachten. –

Antwort

4

Da die Spezifikation für diese Gleichheit nicht von der OrderRule-Klasse, sondern von Ihrer Auflistung stammt, verwenden Sie die Konstruktorüberladung des HashSet, die einen IEqualityComparer akzeptiert.

public class MyOrderRuleComparer : EqualityComparer<OrderRule> 
{ 
    private IEqualityComparer<string> _c = EqualityComparer<string>.Default; 

    public override bool Equals(OrderRule l, OrderRule r) 
    { 
     return _c.Equals(l.Property, r.Property); 
    } 

    public override int GetHashCode(OrderRule rule) 
    { 
     return _c.GetHashCode(rule.Property); 
    } 
} 

...

HashSet<OrderRule> rules = new HashSet(new MyOrderRuleComparer()); 

Bitte beachten Sie, dass als Schlüssel unter Verwendung OrderRule.Property, Sie bedeuten, dass es nicht ändern müssen, nachdem die Instanz zu dem Satz hinzugefügt wird. Aus diesem Grund könnte die Implementierung IEquatable<OrderRule> der beste Ansatz sein, abhängig von Ihrem Entwicklerteam.

+1

Gibt es einen Grund, warum Sie nicht einfach schreiben 'Public bool Gleich (OrderRule l, OrderRule r) {return l.Property == r.Property; } 'aber stattdessen einen expliziten Verweis auf den Standard' IEqualityComparer 'verwenden? –

+0

Btw, Ich mag die Idee, diese Definition von "Gleichheit" auf das HashSet zu beschränken (anstatt die Gleichheit für die ganze Klasse zu überschreiben, was an anderen Stellen unpassend sein kann). Ich wusste nicht, dass HashSet das kann. Macht viel Sinn. –

+0

Es ist nur eine Frage des Stils, denke ich. Auf diese Weise überlasse ich es den .NET-Framework-Implementierern, zu wissen, wie man diesen IEqualityComparer implementiert, anstatt die aktuelle Implementierung aus dem Framework zu kopieren. – wigy

3

Wenn ich zwei OrderRules mit derselben Eigenschaft hinzufügen, aber andere Richtung ich beide noch brauchen

gleich betrachtet werden könnten Sie außer Kraft setzen Equals und GethashCode und/oder implementieren IEquatable<OrderRule>:

public class OrderRule: IEquatable<OrderRule> 
{ 
    public OrderRule(string property) 
    { 
     this.Property = property; 
    } 

    public OrderDirection Direction { get; set; } 
    public String Property { get; } 
    public OrderRule Rule { get; set; } 

    public bool Equals(OrderRule other) 
    { 
     return (other != null && other.Property == this.Property); 
    } 

    public override int GetHashCode() 
    { 
     return Property?.GetHashCode() ?? int.MinValue; 
    } 

    public override bool Equals(object obj) 
    { 
     if (obj == null) 
      return false; 
     if(ReferenceEquals(this, obj)) 
      return true; 
     OrderRule other = obj as OrderRule; 
     return this.Equals(other); 
    } 
} 

Beachten Sie, dass die Eigenschaft schreibgeschützt ist, da Sie eine Eigenschaft oder ein Feld, das in GetHashCode verwendet wird, nicht ändern können sollten.

Why?: „Richtlinie: die ganze Zahl von GetHashCode zurück sollte nie Im Idealfall sollte der Hash-Code eines wandelbaren Objekt ändern, aus nur Feldern berechnet werden, die nicht mutiert und daher der Hash-Wert eines Objektes ist das gleiche für sein ganzes Leben lang. "

Dieser Wert ist z. in einem Wörterbuch oder HashSet verwendet, um den Hashcode zu berechnen. Wenn es sich ändern würde, nachdem das Objekt hinzugefügt wurde, konnte es nicht mehr gefunden werden.

+1

Ich mag, dass Sie erwähnen, dass Property unveränderlich sein sollte, wenn wir es als Schlüssel im Hash verwenden. – wigy

Verwandte Themen