Neu in .NET 8.0 [12]: Eingefrorene Objektmengen
.NET 8.0 bietet zwei neue Objektmengen, bei denen man nach dem Erstellen die Elemente nicht ändern, ergänzen oder löschen kann.

(Bild: Rejdan/Shutterstock.com)
- Dr. Holger Schwichtenberg
.NET 8.0 bietet zwei neue Objektmengen FrozenSet<T>
und FrozenDictionary<T, T>
im neuen Namensraum System.Collections.Frozen
. Bei diesen eingefrorenen Mengen kann man nach der Erstellung weder Elemente ändern, noch ergänzen oder löschen. Dafür liefern sie die enthaltenen Elemente schneller als andere verfügbare Objektmengen in .NET.
Eine eingefrorene Menge erstellt man mit zwei neuen Erweiterungsmethoden fĂĽr die Schnittstelle IEnumerable<T>
:
ToFrozenSet()
gibt die Menge als Instanz vonFrozenSet<T>
zurĂĽckToFrozenDictionary()
gibt die Menge als Instanz vonFrozenDictionary<T, T>
zurĂĽck.
Diese Methoden erstellen eine "eingefrorene" Liste bzw. ein Dictionary (mit Name-Wert-Paaren).
Es gibt drei Unterschiede zwischen der schon seit dem 2005 erschienen .NET Framework 2.0 verfĂĽgbaren ReadOnlyCollection<T>
und dem nun in .NET 8.0 eingefĂĽhrten FrozenSet<T>
:
- Implementierungen von
ReadOnlyCollection<T>
stellen nur die Sicht auf eine andere Menge dar, die man mitAsReadOnly()
erzeugt. Hingegen istFrozentSet<T>
eine eigenständige Menge. FrozenSet<T>
besitzt keinen Indexer:frozenSetĂ—
funktioniert daher nicht.FrozentSet<T>
kann keine Duplikate enthalten, denn Sets erlauben keine Duplikate
Folgender Code zeigt den Einsatz von FrozenSet
im Vergleich zu anderen Objektmengen:
/// <summary>
/// Klasse System.Collections.Frozen.FrozenSet:
/// Eine nur lesbare einfache Liste.
/// Duplikate warden automatisch entfernt!
/// </summary>
public void FrozenSet()
{
CUI.H2(nameof(FrozenSet));
CUI.H3("FrozenSet aus Array");
int[] Zahlen = new int[] { 1, 2, 3 };
var f = Zahlen.ToFrozenSet();
Console.WriteLine(f.GetType().FullName);
CUI.H3("FrozenSet aus List");
List<int> list = new List<int> { 42, 10, 50, 42 };
FrozenSet<int> frozenSet = list.ToFrozenSet();
Console.WriteLine(frozenSet.GetType().FullName);
Console.WriteLine(frozenSet.Count); // nur 3, da keine Duplikate!
#region -------------------
// Ă„nderung --> FrozenSet hat keinen Indexer,
// kein Add(), kein Remove()
//frozenSet[2] = 10; // Ändern nicht möglich
//frozenSet.Add(42); // Hinzufügen nicht möglich!!
//frozenSet.Remove(42); // Hinzufügen nicht möglich!!
#endregion
CUI.H3("ReadOnlyCollection aus List");
// gab es schon vor .NET 8.0 :-) -->
// ReadOnlyCollection<T> ist nur Sicht auf eine andere Menge,
// die man mit AsReadOnly() erzeugt.
ReadOnlyCollection<int> readonlyList = list.AsReadOnly();
Console.WriteLine(readonlyList.GetType().FullName);
//readonlyList[2] = 10; // Ändern nicht möglich
//readonlyList.Add(42); // Hinzufügen nicht möglich!!
CUI.H3("ImmutableList aus List"); // gab es schon vor .NET 8.0 :-)
ImmutableList<int> immutableList = list.ToImmutableList();
Console.WriteLine(immutableList.GetType().FullName);
//immutableList[2] = 10; // Ändern nicht möglich
var newImmutableList = immutableList.Add(42);
// Hinzufügen IST möglich, aber man bekommt eine neue Liste!
#region ------------------- Ă„nderungen in Ursprungsliste
CUI.H3("Ein Element ändern");
list[2] += 1; // drittes Element der Ursprungsliste ändern
Console.WriteLine(list[2]); // 51
Console.WriteLine(readonlyList[2]); // 51
Console.WriteLine(immutableList.ElementAt(2)); // ist immer noch 50!
Console.WriteLine(frozenSet.ElementAt(2)); // ist immer noch 50!
#endregion
#region ------------------- Elemente hinzufĂĽgen in Ursprungsliste
CUI.H3("Ein Element hinzufĂĽgen");
list.Add(77); // Ein fünftes Element ergänzen
Console.WriteLine($"List count: {list.Count}"); // == 5!
// == 5 weil: ReadOnlyList ist eine Sicht auf List<T>!:
Console.WriteLine($"ReadOnlyList count: {readonlyList.Count}");
// == 4 weil vorheriger Zustand der Liste:
Console.WriteLine($"ImmutableList count: {immutableList.Count}");
// == 5 neue Liste:
Console.WriteLine($"new ImmutableList count: {newImmutableList.Count}");
// == 3 FrozenSET: vorheriger Zustand, keine Duplikate:
Console.WriteLine($"FrozenSet count: {frozenSet.Count}");
#endregion
}
Den Einsatz von FrozenDictionary
zeigt folgender Codeausschnitt:
public void FrozenDic()
{
CUI.H2(nameof(FrozenDic));
List<int> list = new List<int> { 42, 10, 50, 42 };
CUI.H3("FrozenDictionary aus List");
FrozenDictionary<int, string> frozenDic =
list.Distinct().ToFrozenDictionary(x => x,
x => "Zahl " + x.ToString());
Console.WriteLine(frozenDic.Count); // 3
// frozenDic[0] = 2;
// frozenDic.TryAdd(0, "Zahl 0"); // "Not supported"
Console.WriteLine(frozenDic.GetType().FullName);
}
}
(rme)