Freigeben über


Einführung in Datensatztypen in C#

Ein Datensatz in C# ist eine Klasse oder Struktur, die spezielle Syntax und Verhalten für das Arbeiten mit Datenmodellen bereitstellt. Der record Modifizierer weist den Compiler an, Elemente zu synthetisieren, die für Typen nützlich sind, deren primäre Rolle Daten speichert. Diese Member enthalten eine Überladung von ToString() und Member, die Wertgleichheit unterstützen.

Wann man Datensätze verwenden sollte

Erwägen Sie die Verwendung eines Datensatzes anstelle einer Klasse oder Anweisung in den folgenden Szenarien:

  • Sie möchten ein Datenmodell definieren, das von Wertgleichstellungabhängt.
  • Sie möchten einen Typ definieren, für den Objekte unveränderlich sind.

Wertgleichheit

Bei Datensätzen bedeutet die Wertgleichstellung, dass zwei Variablen eines Datensatztyps gleich sind, wenn die Typen übereinstimmen und alle Eigenschafts- und Feldwerte gleich sind. Bei anderen Referenztypen wie Klassen bedeutet Gleichheit standardmäßig Referenzgleichheit, sofern nicht Wertgleichstellung implementiert wurde. Das heißt, zwei Variablen eines Klassentyps sind gleich, wenn sie auf dasselbe Objekt verweisen. Methoden und Operatoren, die die Gleichheit von zwei Datensatzinstanzen bestimmen, verwenden die Wertgleichstellung.

Nicht alle Datenmodelle funktionieren gut mit der Wertgleichheit. Beispielsweise hängt Entity Framework Core von der Referenzgleichheit ab, um sicherzustellen, dass nur eine Instanz eines Entitätstyps für das Konzept einer Entität verwendet wird. Aus diesem Grund sind Datensatztypen nicht für die Verwendung als Entitätstypen in Entity Framework Core geeignet.

Unbeweglichkeit

Ein unveränderlicher Typ ist ein Typ, der verhindert, dass Sie eigenschaften- oder Feldwerte eines Objekts ändern, nachdem es instanziiert wurde. Unveränderlichkeit kann nützlich sein, wenn Sie einen Typ als threadsicher benötigen oder abhängig von einem Hashcode sind, der in einer Hashtabelle gleich bleibt. Datensätze bieten eine präzise Syntax zum Erstellen und Arbeiten mit unveränderlichen Typen.

Unveränderlichkeit ist nicht für alle Datenszenarien geeignet. Entity Framework Coreunterstützt z. B. keine Aktualisierung mit unveränderlichen Entitätstypen.

Unterschiede zwischen Datensätzen und Klassen sowie Strukturen

Die Syntax, mit der Klassen oder Strukturen deklariert und instanziiert werden, kann auch für Datensätze verwendet werden. Ersetzen Sie einfach das schlüsselwort class durch das record, oder verwenden Sie record struct anstelle von struct. Ebenso unterstützen Datensatzklassen die Syntax zum Ausdrücken von Vererbungsbeziehungen. Datensätze unterscheiden sich auf folgende Weise von Klassen:

  • Sie können Positionsparameter in einem primären Konstruktor verwenden, um einen Typ mit unveränderlichen Eigenschaften zu erstellen und zu instanziieren.
  • Die Methoden und Operatoren, die bei Klassen die Verweisgleichheit oder -ungleichheit angeben (z. B. Object.Equals(Object) und ==), geben bei Datensätzen die Wertgleichheit oder -ungleichheit an.
  • Sie können einen with Ausdruck verwenden, um eine Kopie eines unveränderlichen Objekts mit neuen Werten in ausgewählten Eigenschaften zu erstellen.
  • Die ToString-Methode eines Datensatzes erstellt eine formatierte Zeichenfolge, die den Typnamen und die Namen und Werte aller öffentlichen Eigenschaften eines Objekts anzeigt.
  • Ein Datensatz kann von einem anderen Datensatz erben. Ein Datensatz kann nicht von einer Klasse erben, und eine Klasse kann nicht von einem Datensatz erben.

Datensatzstrukturen unterscheiden sich von Strukturen darin, dass der Compiler die Methoden für Gleichheit und ToString synthetisiert. Der Compiler synthetisiert eine Deconstruct-Methode für positionelle Datensatzstrukturen.

Der Compiler synthetisiert eine öffentliche Eigenschaft nur für Initialisierung für jeden Parameter eines primären Konstruktors in einer record class. In einer record struct synthetisiert der Compiler eine öffentliche Lese-/Schreibeigenschaft. Der Compiler erstellt keine Eigenschaften für primäre Konstruktorparameter in class und struct Typen, die nicht record Modifizierer enthalten.

Beispiele

Im folgenden Beispiel wird ein öffentlicher Datensatz definiert, der Positionsparameter zum Deklarieren und Instanziieren eines Datensatzes verwendet. Anschließend werden der Typname und die Eigenschaftswerte gedruckt:


public record Person(string FirstName, string LastName);

public static class Program
{
    public static void Main()
    {
        Person person = new("Nancy", "Davolio");
        Console.WriteLine(person);
        // output: Person { FirstName = Nancy, LastName = Davolio }
    }

}

Im folgenden Beispiel wird die Wertgleichstellung in Datensätzen veranschaulicht:

public record Person(string FirstName, string LastName, string[] PhoneNumbers);
public static class Program
{
    public static void Main()
    {
        var phoneNumbers = new string[2];
        Person person1 = new("Nancy", "Davolio", phoneNumbers);
        Person person2 = new("Nancy", "Davolio", phoneNumbers);
        Console.WriteLine(person1 == person2); // output: True

        person1.PhoneNumbers[0] = "555-1234";
        Console.WriteLine(person1 == person2); // output: True

        Console.WriteLine(ReferenceEquals(person1, person2)); // output: False
    }
}

Das folgende Beispiel veranschaulicht die Verwendung eines with Ausdrucks, um ein unveränderliches Objekt zu kopieren und eine der Eigenschaften zu ändern:

public record Person(string FirstName, string LastName)
{
    public required string[] PhoneNumbers { get; init; }
}

public class Program
{
    public static void Main()
    {
        Person person1 = new("Nancy", "Davolio") { PhoneNumbers = new string[1] };
        Console.WriteLine(person1);
        // output: Person { FirstName = Nancy, LastName = Davolio, PhoneNumbers = System.String[] }

        Person person2 = person1 with { FirstName = "John" };
        Console.WriteLine(person2);
        // output: Person { FirstName = John, LastName = Davolio, PhoneNumbers = System.String[] }
        Console.WriteLine(person1 == person2); // output: False

        person2 = person1 with { PhoneNumbers = new string[1] };
        Console.WriteLine(person2);
        // output: Person { FirstName = Nancy, LastName = Davolio, PhoneNumbers = System.String[] }
        Console.WriteLine(person1 == person2); // output: False

        person2 = person1 with { };
        Console.WriteLine(person1 == person2); // output: True
    }
}

Weitere Informationen finden Sie unter Records (C#-Referenz).

C#-Sprachspezifikation

Weitere Informationen finden Sie in der C#-Sprachspezifikation. Die Sprachspezifikation ist die endgültige Quelle für C#-Syntax und -Verwendung.