Erhält HashSet den Anzeigenauftrag?

HashSet die in .NET 3.5 eingeführte HashSet Auflistung die Reihenfolge, in der foreach iteriert wird?

Die Dokumentation besagt, dass die Sammlung nicht sortiert ist, aber nichts über den Anzeigenauftrag sagt. Ein Vorabversion BCL- Blog-Eintrag gibt an, dass es nicht geordnet ist, aber dieser Artikel gibt an, dass es entworfen wird, um Reihenfolge von Anzeigen zu erhalten. Meine begrenzten Tests legen nahe, dass die Reihenfolge erhalten bleibt, aber das könnte ein Zufall sein.

   

Diese HashSet-MSDN-Seite sagt speziell:

Eine Menge ist eine Sammlung, die keine doppelten Elemente enthält und deren Elemente keine bestimmte Reihenfolge haben.

Ich denke, dass der Artikel, der behauptet, dass er Ordnung hält, einfach falsch ist. Bei einfachen Tests kann die Reihenfolge der Anzeigen aufgrund der internen Struktur beibehalten werden, aber dies ist nicht garantiert und wird nicht immer so funktionieren. Ich werde versuchen, ein Gegenbeispiel zu finden.

EDIT: Hier ist das Gegenbeispiel:

 using System; using System.Collections.Generic; class Test { static void Main() { var set = new HashSet(); set.Add(1); set.Add(2); set.Add(3); set.Remove(2); set.Add(4); foreach (int x in set) { Console.WriteLine(x); } } } 

Dies druckt 1, 4, 3 trotz 3 vor 4 eingefügt wurde.

Es ist möglich, dass beim Entfernen von Elementen die Reihenfolge der Anzeigen beibehalten wird. Ich bin mir nicht sicher, aber ich wäre nicht ganz überrascht. Ich denke jedoch, dass es eine sehr schlechte Idee wäre, sich darauf zu verlassen:

  • Es ist nicht dokumentiert, dass dies so funktioniert, und in der Dokumentation wird explizit angegeben, dass es nicht sortiert ist.
  • Ich habe die internen Strukturen oder den Quellcode (die ich offensichtlich nicht habe) nicht angeschaut. Ich müsste sie sorgfältig studieren, bevor ich einen solchen Anspruch auf eine feste Art und Weise geltend mache.
  • Die Implementierung könnte sehr leicht zwischen den Versionen des Frameworks wechseln. Sich darauf zu verlassen wäre, als würde man sich auf die string.GetHashCode Implementierung verlassen, die sich nicht ändert – was einige Leute in den .NET 1.1-Tagen getan haben, und dann wurden sie gebrannt, als sich die Implementierung in .NET 2.0 änderte …

Die Dokumentation besagt:

Eine HashSet < (Of <(T>)>) -Auflistung ist nicht sortiert und kann keine doppelten Elemente enthalten. Wenn die Duplizierung von Aufträgen oder Elementen wichtiger ist als die performance Ihrer Anwendung, sollten Sie die class List < (Of <(T>)>) zusammen mit der Sort-Methode verwenden.

Daher spielt es keine Rolle, ob die Reihenfolge der Elemente in der aktuellen Implementierung tatsächlich beibehalten wird, weil dies nicht dokumentiert ist, und selbst wenn es scheint, dass sich dies zu einem beliebigen Zeitpunkt in der Zukunft ändern kann (selbst in einem Hotfix zu) der Rahmen).

Sie sollten gegen dokumentierte Verträge programmieren, nicht über Implementierungsdetails .

Nein, ein Hash-Set wird die Reihenfolge nicht beibehalten, zumindest nicht vorhersehbar. Sie könnten ein LinkedHashSet (Java) oder ein Äquivalent verwenden. Ein LinkedHashSet wird die Reihenfolge beibehalten.

Wenn Sie bestellen möchten, sollten Sie nicht einmal ein Set verwenden … es ist nicht für bestellte Elemente, außer in Ausnahmefällen.

EDIT: klingt wie ich predige: – / Entschuldigung.

Es gibt speziell eine SortedSet Sammlung in .NET4 .

Dies würde Ihnen eine Sortierung ermöglichen, aber es ist unwahrscheinlich, dass die Sortierreihenfolge für die Anzeigenreihenfolge festgelegt wird. Da Sie einen benutzerdefinierten IComparer , könnten Sie theoretisch alles machen.

Wenn Sie den Quellcode für HashSet.AddIfNotPresent lesen , können Sie sehen, dass der Anzeigenauftrag beibehalten wird, sofern keine Löschungen vorgenommen wurden .

Das new HashSet { "Tom", "Dick", "Harry" } erhält die Reihenfolge, aber wenn Sie dann Dick entfernen und Rick hinzufügen, lautet die Reihenfolge [“Tom”, “Rick”, “Harry”].