Records
Records in C# wurden mit C# 9 eingeführt und stellen eine neue Möglichkeit dar, unveränderliche Datentypen zu modellieren. Im Gegensatz zu klassischen Klassen (class) und Strukturen (struct) fokussieren sich Records auf die Darstellung von Datenobjekten, bei denen Wertgleichheit im Vordergrund steht. Sie sind besonders nützlich, wenn Objekte nur zur Speicherung von Zuständen und nicht zur Steuerung komplexer Logik benötigt werden. Durch ihre vereinfachte Syntax lassen sich Datenstrukturen klarer und sicherer modellieren, ohne unnötige Boilerplate-Codefragmente wie Equals, GetHashCode oder ToString manuell implementieren zu müssen.
In der modernen Softwareentwicklung – insbesondere in Architekturen wie DDD (Domain Driven Design), Event Sourcing oder bei Implementierungen von DTOs (Data Transfer Objects) – bieten Records einen enormen Mehrwert. Sie helfen dabei, Datenobjekte klar von Verhaltensobjekten zu trennen und fördern dadurch eine saubere Trennung der Verantwortlichkeiten.
In diesem Tutorial lernen Sie, wie Records syntaktisch aufgebaut sind, welche Unterschiede es zu Klassen und Strukturen gibt und wie Records effizient in Algorithmen, Datenstrukturen und OOP-Prinzipien integriert werden können. Darüber hinaus werden typische Anwendungsfälle, Fallstricke und Best Practices aufgezeigt, sodass Records als fester Bestandteil Ihrer C#-Projekte etabliert werden können. Am Ende sind Sie in der Lage, Records gezielt in realen Projekten einzusetzen und architektonisch sinnvoll zu nutzen.
Grundlegendes Beispiel
textusing System;
public record Person(string Vorname, string Nachname);
public class Program
{
public static void Main()
{
var person1 = new Person("Anna", "Müller");
var person2 = new Person("Anna", "Müller");
var person3 = new Person("Peter", "Schmidt");
Console.WriteLine(person1);
Console.WriteLine(person1 == person2);
Console.WriteLine(person1 == person3);
}
}
Im obigen Beispiel sehen wir die Basissyntax eines Records in C#. Der Record "Person" wird mit einem so genannten Primary Constructor definiert, der gleichzeitig Felder und Eigenschaften erzeugt. Dadurch sparen wir viel Boilerplate-Code im Vergleich zu einer klassischen Klasse.
Die Instanzen person1 und person2 besitzen dieselben Werte und sind daher gleich. Records basieren auf Wertgleichheit und nicht auf Referenzgleichheit. Dies bedeutet, dass der Vergleichsoperator "==" automatisch überschrieben wird, um die Werte der Properties zu vergleichen, anstatt nur die Speicheradressen zu prüfen. Dies ist ein entscheidender Unterschied zu Klassen, wo "==" standardmäßig auf Referenzgleichheit prüft.
Mit Console.WriteLine(person1) wird automatisch die ToString()-Methode verwendet, die bei Records standardmäßig überschrieben wird. Das Ergebnis ist eine strukturierte Ausgabe des Record-Inhalts, was die Debugging- und Logging-Fähigkeiten verbessert.
Ein weiteres zentrales Konzept ist die Unveränderlichkeit: Records sind per Default immutable. Das bedeutet, dass einmal zugewiesene Werte nicht verändert werden können, es sei denn, man nutzt spezielle Mechanismen wie "with"-Ausdrücke. Diese Immutability unterstützt nicht nur die Sicherheit von Daten, sondern reduziert auch Fehlerquellen im Mehrthreading-Umfeld.
In realen Projekten werden Records typischerweise für DTOs oder als Value Objects in DDD genutzt. Gerade in komplexen Softwarearchitekturen erleichtern Records die Implementierung stabiler und effizienter Systeme, indem sie klare, unveränderliche Datenrepräsentationen bieten.
Praktisches Beispiel
textusing System;
using System.Collections.Generic;
public record Produkt(int Id, string Name, decimal Preis);
public class Warenkorb
{
private readonly List<Produkt> _produkte = new();
public void Hinzufügen(Produkt produkt)
{
if (_produkte.Contains(produkt))
{
Console.WriteLine($"Produkt {produkt.Name} ist bereits im Warenkorb.");
return;
}
_produkte.Add(produkt);
Console.WriteLine($"Produkt {produkt.Name} hinzugefügt.");
}
public decimal BerechneGesamtpreis()
{
decimal summe = 0;
foreach (var p in _produkte)
{
summe += p.Preis;
}
return summe;
}
}
public class Program
{
public static void Main()
{
var produkt1 = new Produkt(1, "Laptop", 1200.50m);
var produkt2 = new Produkt(2, "Maus", 25.99m);
var produkt3 = new Produkt(1, "Laptop", 1200.50m);
var warenkorb = new Warenkorb();
warenkorb.Hinzufügen(produkt1);
warenkorb.Hinzufügen(produkt2);
warenkorb.Hinzufügen(produkt3);
Console.WriteLine($"Gesamtpreis: {warenkorb.BerechneGesamtpreis()} EUR");
}
}
Best Practices und typische Fallstricke bei der Arbeit mit Records in C#:
Records sollten gezielt dann eingesetzt werden, wenn unveränderliche Datenobjekte benötigt werden, die sich durch Wertgleichheit auszeichnen. Achten Sie darauf, Records nicht unnötig für Objekte mit komplexer Logik oder Zustandsänderungen einzusetzen, da dafür Klassen besser geeignet sind.
Häufige Fehler entstehen, wenn Entwickler versuchen, Records nachträglich zu mutieren. Zwar können Records Properties mit set definieren, jedoch unterläuft dies den immutablen Charakter. Eine bessere Lösung ist der Einsatz von "with"-Ausdrücken, um neue Instanzen mit veränderten Werten zu erstellen.
Auch beim Umgang mit Collections ist Vorsicht geboten: Während Records HashCode-Implementierungen automatisch generieren, können sich Probleme ergeben, wenn die Werte nachträglich geändert werden. Dies kann zu unerwartetem Verhalten in Dictionaries oder HashSets führen.
Zur Fehlersuche empfiehlt es sich, die automatisch generierten Methoden wie ToString() und Equals() zu nutzen, um Datenkonsistenz zu prüfen. Performance-Optimierungen sollten insbesondere in Szenarien mit großen Mengen an Records bedacht werden, beispielsweise durch effiziente Nutzung von HashSets oder durch Minimierung unnötiger Kopien via with-Ausdrücke.
Sicherheitsaspekte: Records sollten keine sensiblen Daten wie Passwörter oder Schlüssel enthalten, da ToString() automatisch Inhalte preisgibt. Verwenden Sie in solchen Fällen entweder Klassen oder überschreiben Sie ToString(), um keine vertraulichen Informationen offenzulegen.
📊 Referenztabelle
C# Element/Concept | Description | Usage Example |
---|---|---|
Record-Deklaration | Erzeugt unveränderliche Datentypen mit Wertgleichheit | public record Person(string Name, int Alter); |
Wertgleichheit | Vergleich basiert auf Property-Werten statt Referenzen | person1 == person2 |
with-Ausdruck | Erzeugt neue Instanz mit modifizierten Werten | var neuePerson = person1 with { Alter = 30 }; |
Automatische Methoden | Equals, GetHashCode, ToString werden generiert | Console.WriteLine(person1); |
Immutability | Standardmäßig sind Properties readonly | public record Produkt(int Id, string Name); |
Zusammenfassung und nächste Schritte in C#:
Records sind ein mächtiges Feature in C#, das die Entwicklung unveränderlicher, leicht vergleichbarer Datenobjekte erheblich vereinfacht. Sie unterstützen die Umsetzung sauberer Softwarearchitekturen, insbesondere in DDD, Event Sourcing oder bei der Arbeit mit DTOs. Die Vorteile liegen in der automatischen Implementierung von Equals, GetHashCode und ToString, wodurch Entwickler sich stärker auf die Geschäftslogik konzentrieren können.
Als nächster Schritt bietet es sich an, tiefer in die Kombination von Records mit Pattern Matching und LINQ einzutauchen. Auch die Integration von Records in asynchrone Szenarien oder die Verwendung innerhalb von API-Designs (z. B. für Request/Response-Objekte) ist ein wichtiger Lernpfad.
Praktischer Rat: Verwenden Sie Records gezielt für Value Objects und unveränderliche Datenstrukturen, aber greifen Sie auf Klassen zurück, wenn komplexe Zustandsverwaltung erforderlich ist.
Für weiterführendes Lernen empfehlen sich Themen wie Pattern Matching in C#, Immutable Collections sowie die vertiefte Anwendung von Records in Domain Driven Design. Dadurch erweitern Sie nicht nur Ihr technisches Verständnis, sondern auch Ihre Fähigkeit, Records in skalierbaren Softwarearchitekturen effektiv einzusetzen.
🧠 Testen Sie Ihr Wissen
Test Your Knowledge
Test your understanding of this topic with practical questions.
📝 Anweisungen
- Lesen Sie jede Frage sorgfältig
- Wählen Sie die beste Antwort für jede Frage
- Sie können das Quiz so oft wiederholen, wie Sie möchten
- Ihr Fortschritt wird oben angezeigt