2016-04-30 8 views
1

Ich habe ein Wörterbuch:ContainsKey im Wörterbuch von Hashset <myClass>

Dictionary<HashSet<myClass>, List<MyObj>> myDict = ... 

Und ich habe:

HashSet<myClass> myHashSet = ... 

ich überprüfen möchten, ob das Wörterbuch (myDict) enthält myHashSet.

Ich habe versucht, zwei Methoden außer Kraft zu setzen:

1) gleich

2)

GetHashCode
public class myClass 
{ 
    public string id; 
    public int number; 

    public override bool Equals(object obj) 
    { 
     myClass other = obj as myClass; 
     bool ret = false; 
     if (other != null) 
     { 
      ret = (this.number == other.number) && (this.id == other.id); 
     } 
     return ret; 
    } 

    public override int GetHashCode() 
    { 
     return this.number^this.id.GetHashCode(); 
    } 
}; 

Leider ein Schlüssel, der im Wörterbuch gefunden wird, gibt false für den Code: myDict.ContainsKey(myHashSet)

Jede Hilfe wird geschätzt!

Antwort

1

überschreiben die GetHasCode und Equal ist beim Vergleichen von Instanzen von myClass.

Hier ist ein Beispiel für die Verwendung von ContainsKey, die nach Objekten Referenz überprüft.

Dictionary<HashSet<string>, List<string>> hashSetDictionary = new Dictionary<HashSet<string>, List<string>>(); 
      var myHashSet = new HashSet<string>(); 

      hashSetDictionary.Add(myHashSet, null); 
      Console.WriteLine(hashSetDictionary.ContainsKey(myHashSet)); 

Hier ist ein Update auf Ihren Code

public class myClass 
    { 
     public myClass(string text, int num) 
     { 
      this.Text = text; 
      this.Num = num; 
     } 

     public string Text { get; set; } 
     public int Num { get; set; } 
    } 

    public class MyObj { } 

    public class AlwaysTrueHashSet<T> : HashSet<T> 
    { 
     public override bool Equals(object obj) 
     { 
      return this.GetHashCode() == obj.GetHashCode(); 
     } 

     public override int GetHashCode() 
     { 
      return "Counting hashcode".GetHashCode(); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 


      Dictionary<HashSet<myClass>, List<MyObj>> myDict = new Dictionary<HashSet<myClass>, 


      List<MyObj>>(); 
      var myHashSet1 = new AlwaysTrueHashSet<myClass>(); 
      myHashSet1.Add(new myClass("123", 5)); 
      myDict.Add(myHashSet1, null); 



      var myHashSet2 = new AlwaysTrueHashSet<myClass>(); 
      myHashSet2.Add(new myClass("123", 5)); 

      /* 
      * when containsKey is invoked, it's checking if the reference of myHashSet2 is the same as myHashSet1. 
      * That's the default behavior. 
      * 
      * extend HashSet, and override the gethashcode and equal methods 
      */ 
      if (myDict.ContainsKey(myHashSet2)) 
      { 
       Console.WriteLine("in"); 
       int i = 3; // it doesn't get this line } 
      } 
     } 
    } 
+0

Es funktioniert nicht, wenn die Hashset einer Klasse ist: Dictionary , List > myDict = new Dictionary , List >(); HashSet myHashSet1 = neuer HashSet (); myHashSet1.Add (neue myClass ("123", 5)); myDict.Add (myHashSet1, null); HashSet myHashSet2 = neuer HashSet (); myHashSet2.Add (neue myClass ("123", 5)); if (myDict.ContainsKey (myHashSet2)) { int i = 3; // Es wird nicht diese Zeile } –

+0

Ihr Code wird immer false zurückgeben. Ich habe meinen Code aktualisiert. – dfdsfdsfsdf

+0

Wenn Sie myClass überschreiben, gilt dies nur für den Vergleich von zwei Instanzen von myClass. Wenn Sie HashSet vergleichen möchten, müssen Sie es erweitern und die Logik bereitstellen. Andernfalls wird es als Referenz verglichen. – dfdsfdsfsdf

2

Nur weil du myClass overrode 's Equals( und GetHashCode() nicht das bedeutet, dass Sie HashSet<myClass> overrode' s Equals( und GetHashCode(), ist das, was wird verwendet, wenn Sie die Wörterbuchsuche durchführen.

Wenn Sie möchten, dass es funktioniert, müssen Sie einen IEqualityComparer<HashSet<myClass>> an den Konstruktor des Wörterbuchs übergeben, damit es diesen Vergleich bei der Wörterbuchsuche verwendet.

public class myClassSetComperer : IEqualityComparer<HashSet<myClass>> 
{ 
    public bool Equals(HashSet<myClass> x, HashSet<myClass> y) 
    { 
     if (ReferenceEquals(x, y)) return true; 
     if (ReferenceEquals(null, x)) return false; 
     if (ReferenceEquals(null, y)) return false; 
     return x.SetEquals(y); 
    } 

    public int GetHashCode(HashSet<myClass> obj) 
    { 
     unchecked 
     { 
      int x = 0; 
      foreach (var myClass in obj) 
      { 
       x = (x*397)^myClass?.GetHashCode() ?? 0; 
      } 
      return x; 
     } 
    } 
} 

//elsewhere 
Dictionary<HashSet<myClass>, List<MyObj>> myDict = new Dictionary<HashSet<myClass>, List<MyObj>>(new myClassSetComperer()); 

SEHR WICHTIG: Dictionary-Tasten (und Hash-Sets) brechen schrecklich, wenn Sie etwas tun, was Equals( oder GetHashCode() verursacht einmal als Suchschlüssel setzen in ändern. Wenn Sie das Objekt HashSet<myClass> oder eines der Objekte myClass ändern, nachdem Sie es in das Wörterbuch eingefügt haben, werden Sie das Wörterbuch und möglicherweise das HashSet beschädigen. Siehe this very good blog post von Eric Lippert auf "Richtlinien und Regeln für GetHashCode"

Verwandte Themen