Behält die HashSet
in .NET 3.5 eingeführte Sammlung die Einfügereihenfolge bei, wenn sie mit iteriert wird foreach
?
In der Dokumentation heißt es, dass die Sammlung nicht sortiert ist, aber nichts über die Einfügereihenfolge aussagt. In einem BCL- Blogeintrag vor der Veröffentlichung wird angegeben , dass er ungeordnet ist. In diesem Artikel wird jedoch angegeben , dass die Einfügereihenfolge beibehalten werden soll. Meine begrenzten Tests legen nahe, dass die Reihenfolge erhalten bleibt, aber das könnte ein Zufall sein.
new HashSet<int>() { 6, 8 }.ToList()
kehrt [6,8] zurück, abernew HashSet<int>() { 8, 6 }.ToList()
[8,6]Antworten:
Auf dieser HashSet-MSDN-Seite heißt es speziell:
quelle
Ich denke, der Artikel, der behauptet, er bewahre die Bestellung, ist einfach falsch. Bei einfachen Tests kann die Einfügereihenfolge aufgrund der internen Struktur zwar beibehalten werden, sie ist jedoch nicht garantiert und funktioniert nicht immer so. 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<int>(); 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, obwohl 3 vor 4 eingefügt wurde.
Es ist möglich, dass die Einfügereihenfolge beibehalten wird, wenn Sie niemals Elemente entfernen. 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:
string.GetHashCode
Umsetzung nicht zu ändern - die einige Leute in den .NET 1,1 Tagen taten zurück, und dann wurde sie verbrannt , wenn die Umsetzung tut Änderung in .NET 2.0 ...quelle
foreach
iteriert nicht in der richtigen Reihenfolge. Verwenden Sie immer 'für' und Indizes.MoveNext
zurückgegeben werden. Für jeden mir bekannten geordneten Typ entspricht dies der Reihenfolge, in der der Index verwendet wird. Beachten Sie, dass in der in Rede stehenden Art (HashSet<T>
) gibt ist kein Indexer. Können Sie ein konkretes Beispiel geben, bei dem Sie der Meinung sind, dass es besser ist, einen Index als eine foreach-Schleife zu verwenden?In der Dokumentation heißt es:
Daher spielt es keine Rolle, ob die Reihenfolge der Elemente in der aktuellen Implementierung tatsächlich beibehalten wird, da dies nicht dokumentiert ist, und selbst wenn es jetzt so aussieht, kann sich dies zu jedem Zeitpunkt in der Zukunft ändern (selbst in einem Hotfix zu der Rahmen).
Sie sollten anhand dokumentierter Verträge programmieren , nicht anhand von Implementierungsdetails .
quelle
SortedSet<T>
In .NET4 gibt es speziell eine Sammlung .Dies würde Ihnen eine Sortierung geben, aber es ist unwahrscheinlich, dass es sich um eine Sortierreihenfolge handelt. Da Sie eine benutzerdefinierte verwenden können, können
IComparer
Sie theoretisch alles tun.quelle
Nein, ein Hash-Satz behält die Einfügereihenfolge nicht bei, zumindest nicht vorhersehbar. Sie können ein LinkedHashSet (Java) oder ein gleichwertiges verwenden. Ein LinkedHashSet behält die Ordnung bei.
Wenn Sie bestellen möchten, sollten Sie nicht einmal ein Set verwenden... es ist nicht für bestellte Elemente gedacht, außer in Ausnahmefällen.EDIT: klingt wie ich predige: - / Sorry.
quelle
Wenn Sie den Quellcode für HashSet.AddIfNotPresent lesen, sehen Sie, dass die Einfügereihenfolge beibehalten wird, vorausgesetzt, es wurden keine Löschvorgänge durchgeführt .
So
new HashSet<string> { "Tom", "Dick", "Harry" }
bleibt die Ordnung erhalten, aber wenn Sie dann Dick entfernen und Rick hinzufügen, lautet die Reihenfolge ["Tom", "Rick", "Harry"].quelle