LINQ .NET 9 | CountBy AggregateBy neue Methoden Tutorial

LINQ .NET 9: Neue Operatoren CountBy & AggregateBy einfach erklärt
Morris M. | Softwareentwickler
03/2024

Effizientere LINQ-Queries in .NET 9: CountBy() und AggregateBy() im Einsatz

Am 13. Februar ist die erste Preview für .NET 9 erschienen und beinhaltet direkt praktisch nützliche Änderungen für Entwickler. Die beiden neu implementierten LINQ-Methoden werden den Umgang mit Listen in Zukunft an einigen Stellen vereinfachen.

CountBy()

Die erste neue Query repliziert ein oft gebrauchtes, aber bislang nicht mit .NET-Bordmitteln umsetzbares Feature: Das Abzählen von Listenelementen anhand eines bestimmten Schlüssels.

Nehmen wir im Folgenden an, dass wir eine Liste von Patienten verarbeiten, denen jeweils ein einzelner Pfleger zugeordnet ist.

1record Patient(string Pfleger, int PatientenNummer); 
2var Patienten = new List<Patient>() 
3{ 
4    new Patient("Hans", 1), 
5    new Patient("Sarah", 2), 
6    new Patient("Kai", 3), 
7    new Patient("Wurst", 4), 
8    new Patient("Hans", 5), 
9    new Patient("Sarah", 6), 
10};

Da uns unsere Pfleger am Herzen liegen, wollen wir darauf Acht geben, dass keiner von ihnen überlastet wird und uns alle Pfleger anzeigen lassen, die derzeit mehr als einem Patienten zugeordnet sind.

Hier kommt die neue Query CountBy() ins Spiel, der wir einfach den Namen des Pflegers als Schlüssel übergeben und eine Liste von Schlüssel-Wert-Paaren aller Pfleger mit der Zahl ihrer Patienten zurückbekommen.

1var pflegerUeberlastung = Patienten.CountBy(p => p.Pfleger);

Das Resultat sieht wie folgt aus:

Natürlich wollen wir, wie eingangs erwähnt, nur die überbelegten Pfleger anzeigen, weshalb wir einen Filter hinten anhängen, der nur die Pfleger auswählt, die mehr als einen Patienten haben. Diese können wir dann bequem in unser Programm zurückschreiben.

Und so sieht die Ausgabe dann aus:

1var pflegerUeberlastung = Patienten.CountBy(p => p.Pfleger).Where(x => x.Value > 1); 
2
3foreach (var (pfleger, anzahl) in pflegerUeberlastung) 
4{ 
5    Console.WriteLine($"{pfleger} hat {anzahl} Patienten"); 
6}

AggregateBy()

Treten wir einen Schritt zurück und betrachten das ganze Krankenhaus, welches aus mehreren Stationen besteht.

1record Station(string StationsName, int BelegteBetten); 
2
3var Stationen = new List<Station>() 
4{ 
5    new Station("Notaufnahme", 39), 
6    new Station("Radiologie", 10), 
7    new Station("Chirurgie", 14), 
8    new Station("Intensivstation", 38), 
9    new Station("Neurologie", 4), 
10};

Ganz schön viel los! Damit wir unser Personal besser planen können, möchte unser Direktor gerne wissen, wie viele Intensivpfleger er für die Kombination aus Notaufnahme und Intensivstation bereitstellen muss. Um dies herauszufinden, können wir die neue AggregateBy()-Methode verwenden.

1Stationen.AggregateBy(
2    keySelector: station => station.StationsName.Contains("Notaufnahme") || station.StationsName.Contains("Intensivstation"), 
3    seed: 0, 
4    (belegteBetten, curr) => belegteBetten + curr.BelegteBetten
5);

Als Schlüssel übergeben wir die Namen der Stationen, die wir aggregieren wollen. (Hinweis: Da wir abfragen wollen, ob die jeweilige Station in unser Schema passt, verwenden wir hier den keySelector und füttern ihn mit unserer Abfrage.) Da wir davon ausgehen, dass es keine weiteren Betten mit Intensivpflegerbedarf außerhalb unserer Stationen gibt, initialisieren wir die Funktion bei 0.Schlussendlich stellen wir noch die Aggregationslogik als Funktion zur Verfügung: Sie summiert einfach die jeweils angegebenen belegten Betten der Station auf.

Da unsere Aggregation eine Auswahl trifft zwischen zutreffenden und nichtzutreffenden Stationen, filtern wir anschließend noch das zurückgegebene Enumerable auf die Einträge, die unseren Schlüssel erfüllt haben. Dann lesen wir der Einfachheit halber direkt den eigentlichen Wert aus und können ihn sofort anzeigen lassen.

1Stationen.AggregateBy(
2    keySelector: station => station.StationsName.Contains("Notaufnahme") || station.StationsName.Contains("Intensivstation"), 
3    seed: 0, 
4    (belegteBetten, curr) => belegteBetten + curr.BelegteBetten
5)
6.First(x => x.Key) 
7.Value;

Und schon bekommen wir unser Ergebnis, und der Direktor kann seinen Plan erstellen!

Wie Sie sehen, stellen die Neuerungen in .NET 9 uns praktische Funktionen zur Verfügung, die das Abfragen oft gebrauchter Informationen vereinfachen werden.

Github-Archiv: https://github.com/MMuellerDevware/Neue-LINQ-Queries-in-.NET-9

Mehr zum Thema

Pfeil nach rechts (Verlinkung)
FluentValidation in Blazor: Validierungslogik mit Custom Rules und Feldern
04/2025

Blazor FluentValidation | C# Validation Best Practices

Pfeil nach rechts (Verlinkung)
.NET 8 API-Versionierung: RESTful Design und URL-Versionierung für APIs
01/2025

.NET 8 API Versioning | RESTful API Management Guide

Pfeil nach rechts (Verlinkung)
Liskov Principle: Schnittstellenfehler & Sicherheitslücken vermeiden
12/2024

Solid Reihe - Liskov Substitution Principle

Pfeil nach rechts (Verlinkung)
Open/Closed Principle: Erweiterbare Software dank klarer Struktur
11/2024

Solid Reihe - Open Close Principle

Pfeil nach rechts (Verlinkung)

Gemeinsam Großes schaffen

Devware GmbH verpflichtet sich, Ihre Privatsphäre zu schützen. Wir benötigen Ihre Kontaktinformationen, um Sie bezüglich unserer Produkte und Dienstleistungen zu kontaktieren. Mit Klick auf Absenden geben Sie sich damit einverstanden. Weitere Informationen finden Sie unter Datenschutz.
Vielen Dank für Ihr Vertrauen.
Unser Team prüft Ihre Anfrage sorgfältig und meldet sich in der Regel innerhalb von 48 Stunden bei Ihnen zurück.
Falls es besonders eilig ist, erreichen Sie uns auch telefonisch:
+ 49 (0) 202 478 269 0.
Da ist etwas schief gegangen beim Absenden des Formulars.