HashSets halten die Elemente nicht eindeutig, wenn Sie ihre Identität ändern

Bei der Arbeit mitHashSets In C # bin ich kürzlich auf ein nerviges Problem gestoßen:HashSets garantieren Sie nicht die Einheitlichkeit der Elemente; Sie sind keine Sets. Was sie garantieren, ist das wennAdd(T item) heißt das Element wird nicht hinzugefügt, wenn für ein Element in der Mengeitem.equals(that) isttrue. Dies gilt nicht mehr, wenn Sie Elemente bearbeiten, die sich bereits im Set befinden. Ein kleines Programm, das demonstriert (Copypasta von meinem Linqpad):

void Main()
{
    HashSet<Tester> testset = new HashSet<Tester>();
    testset.Add(new Tester(1));
    testset.Add(new Tester(2));
    foreach(Tester tester in testset){
      tester.Dump();
    }
    foreach(Tester tester in testset){
      tester.myint = 3;
    }
    foreach(Tester tester in testset){
      tester.Dump();
    }
    HashSet<Tester> secondhashset = new HashSet<Tester>(testset);
    foreach(Tester tester in secondhashset){
      tester.Dump();
    }
}

class Tester{
  public int myint;

  public Tester(int i){
    this.myint = i;
  }

  public override bool Equals(object o){
    if (o== null) return false;
    Tester that = o as Tester;
    if (that == null) return false;
    return (this.myint == that.myint);
  }

  public override int GetHashCode(){
    return this.myint;
  }

  public override string ToString(){
    return this.myint.ToString();
  }
}

Die Elemente in der Auflistung werden problemlos so bearbeitet, dass sie gleich sind, und nur dann herausgefiltert, wenn ein neues HashSet erstellt wird. Was ist ratsam, wenn ich mit Sets arbeiten möchte, bei denen ich wissen muss, dass die Einträge eindeutig sind? Roll my own, wobei Add (T item) eine Kopie vom Item hinzufügt und der Enumerator über Kopien der enthaltenen Items auflistet? Dies stellt die Herausforderung dar, dass jedes enthaltene Element zumindest in seinen Elementen, die die Gleichheit beeinflussen, tief kopierbar sein sollte.

Eine andere Lösung wäre, Ihre eigenen zu erstellen und nur Elemente zu akzeptieren, die INotifyPropertyChanged implementieren, und Maßnahmen zu ergreifen, um die Gleichheit erneut zu überprüfen. Dies scheint jedoch stark einschränkend zu sein, ganz zu schweigen von viel Arbeit und Leistungsverlust unter der Haube .

Eine weitere mögliche Lösung besteht darin, sicherzustellen, dass alle Felder im Konstruktor readonly oder const sind. Alle Lösungen scheinen sehr große Nachteile zu haben. Habe ich noch andere Möglichkeiten?

Antworten auf die Frage(3)

Ihre Antwort auf die Frage