Neu in .NET 6 [12]: PriorityQueue - Warteschlange mit Prioritäten

Der Dotnet-Doktor Holger Schwichtenberg  –  9 Kommentare

Die neue Klasse PriorityQueue bietet eine FIFO-Liste mit Prioritäten.

Die Klasse System.Collections.Queue gibt es seit .NET Framework 1.0 (Jahr 2001); das generische Pendant System.Collections.Generic.Queue<Typ> seit .NET Framework 2.0 (Jahr 2005).

In diesem Jahr ist in .NET 6 die Klasse System.Collections.Generic.PriorityQueue <Typ,Prio> hinzugekommen, die die Einträge in der Warteschlange nach den angegebenen Prioritäten wieder ausliefert. Das Objekt mit dem niedrigsten Wert bei der Priorität liefert sie zuerst.

Der Code

var pq = new PriorityQueue<string, int>();
pq.Enqueue("Christian", 3);
pq.Enqueue("Annalena", 2);
pq.Enqueue("Olaf", 1);
pq.Enqueue("Robert", 2);
pq.Enqueue("Armin", 4);
pq.Enqueue("Janine", 3);
pq.Enqueue("Susanne", 3);
while (pq.TryDequeue(out string name, out int prio))
{
Console.WriteLine($"Name: {name} - Prio: {prio}");
}

liefert folgende Ausgabe:

Name: Olaf - Prio: 1
Name: Annalena - Prio: 2
Name: Robert - Prio: 2
Name: Christian - Prio: 3
Name: Janine - Prio: 3
Name: Susanne - Prio: 3
Name: Armin - Prio: 4

Wir sehen: Bei gleichen Prioritäten entscheidet die Reihenfolge des Eingangs in die Warteschlange. Das stand zum Release von .NET 6 nicht in der Dokumentation, wurde erst am 17.11. ergänzt. Dennoch fällt die Dokumentation bei allen neueren .NET-Klassen spärlich aus im Vergleich zu den alten .NET-Klassen wie Queue<Typ>.

Etwas mehr zum Hintergrund der neuen Klasse PriorityQueue findet man in den Diskussionen auf GitHub. Dort kann man zum Beispiel nachlesen, dass man die Prioritäten in der Warteschlange nicht ändern kann und der Typ nicht IEnumerable implementiert, also nicht mit foreach aufzählbar ist.

Wer unbedingt foreach nutzen will, kann diese Erweiterungsmethode hinzufügen:

public static class PriorityQueueExtensions
{
public static IEnumerable<TElement> GetEnumerator<TElement, TPriority>
(this PriorityQueue<TElement, TPriority> queue)
{
while (queue.TryDequeue(out var item, out TPriority priority))
yield return item;
}
}

Danach kann man schreiben:

foreach (var item in pq.GetEnumerator())
{
Console.WriteLine(item);
}