Úvod do typů záznamů v jazyce C#

Záznam v jazyce C# je třída nebo struktura, která poskytuje speciální syntaxi a chování pro práci s datovými modely. record Modifikátor dává kompilátoru pokyn, aby syntetizoval členy, které jsou užitečné pro typy, jejichž primární role ukládá data. Mezi tyto členy patří přetížení ToString() a členy, které podporují rovnost hodnot.

Kdy použít záznamy

Zvažte použití záznamu místo třídy nebo struktury v následujících scénářích:

  • Chcete definovat datový model, který závisí na rovnosti hodnot.
  • Chcete definovat typ, pro který objekty jsou neměnné.

Rovnost hodnot

Pro záznamy rovnost hodnot znamená, že dvě proměnné typu záznamu jsou stejné, pokud se typy shodují a všechny hodnoty vlastností a polí se shodují. Pro jiné odkazové typy, jako jsou třídy, rovnost znamená rovnost odkazů. To znamená, že dvě proměnné typu třídy jsou stejné, pokud odkazují na stejný objekt. Metody a operátory, které určují rovnost dvou instancí záznamů, používají rovnost hodnot.

Ne všechny datové modely dobře fungují s rovností hodnot. Například Entity Framework Core závisí na rovnosti odkazů, aby se zajistilo, že používá pouze jednu instanci typu entity pro to, co je koncepčně jedna entita. Z tohoto důvodu nejsou typy záznamů vhodné pro použití jako typy entit v Entity Framework Core.

Neměnitelnost

Neměnný typ je typ, který vám brání ve změně jakékoli vlastnosti nebo hodnoty polí objektu po vytvoření instance. Neměnnost může být užitečná v případě, že potřebujete typ bezpečný pro přístup z více vláken nebo v závislosti na zbývajícím hashovacím kódu v tabulce hash. Záznamy poskytují stručnou syntaxi pro vytváření a práci s neměnnými typy.

Neměnnost není vhodná pro všechny scénáře dat. Entity Framework Core například nepodporuje aktualizaci pomocí neměnných typů entit.

Jak se záznamy liší od tříd a struktur

Stejnou syntaxi, která deklaruje a vytváří instance tříd nebo struktur, lze použít se záznamy. Stačí nahradit class klíčové slovo slovem record, nebo použít record struct místo struct. Stejně tak je stejná syntaxe pro vyjádření vztahů dědičnosti podporována třídami záznamů. Záznamy se liší od tříd následujícími způsoby:

  • Poziční parametry v primárním konstruktoru můžete použít k vytvoření a vytvoření instance typu s neměnnými vlastnostmi.
  • Stejné metody a operátory, které označují rovnost nebo nerovnost ve třídách (například Object.Equals(Object) a), označují rovnost hodnot nebo nerovnost==v záznamech.
  • Pomocí výrazu with můžete vytvořit kopii neměnného objektu s novými hodnotami ve vybraných vlastnostech.
  • Metoda záznamu ToString vytvoří formátovaný řetězec, který zobrazuje název typu objektu a názvy a hodnoty všech jeho veřejných vlastností.
  • Záznam může dědit z jiného záznamu. Záznam nemůže dědit z třídy a třída nemůže dědit ze záznamu.

Struktury záznamů se liší od struktur v tom, že kompilátor syntetizuje metody rovnosti a ToString. Kompilátor syntetizuje metodu Deconstruct pro struktury pozičních záznamů.

Kompilátor syntetizuje veřejnou inicializační vlastnost pro každý primární konstruktor parametr v objektu record class. V kompilátoru record structsyntetizuje veřejnou vlastnost pro čtení i zápis. Kompilátor nevytvoří vlastnosti pro parametry primárního konstruktoru v class a struct typech, které neobsahují record modifikátor.

Příklady

Následující příklad definuje veřejný záznam, který používá poziční parametry k deklaraci a vytvoření instance záznamu. Potom vytiskne hodnoty názvu a vlastnosti typu:


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 }
    }

}

Následující příklad ukazuje rovnost hodnot v záznamech:

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
    }
}

Následující příklad ukazuje použití with výrazu ke zkopírování neměnného objektu a změně jedné z vlastností:

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
    }
}

Další informace najdete v tématu Záznamy (referenční dokumentace jazyka C#).

Specifikace jazyka C#

Další informace najdete v tématu Specifikace jazyka C#. Specifikace jazyka je úplným a rozhodujícím zdrojem pro syntaxi a použití jazyka C#.