Introduktion till posttyper i C#

En post i C# är en klass eller struct som tillhandahåller särskild syntax och beteende för att arbeta med datamodeller. Modifieraren record instruerar kompilatorn att syntetisera medlemmar som är användbara för typer vars primära roll är att lagra data. Dessa medlemmar innehåller en överbelastning av ToString() och medlemmar som stöder värdejämlikhet.

När poster ska användas

Överväg att använda en post i stället för en klass eller struct i följande scenarier:

Värdejämlikhet

För poster innebär värdejämlikhet att två variabler av en posttyp är lika om typerna matchar och alla egenskaps- och fältvärden matchar. För andra referenstyper, till exempel klasser, innebär likhet referensjämlikhet. Det innebär att två variabler av en klasstyp är lika med om de refererar till samma objekt. Metoder och operatorer som avgör likheten mellan två postinstanser använder värdejämlikhet.

Alla datamodeller fungerar inte bra med värdejämlikhet. Entity Framework Core är till exempel beroende av referensjämlikhet för att säkerställa att den endast använder en instans av en entitetstyp för vad som konceptuellt är en entitet. Därför är posttyper inte lämpliga för användning som entitetstyper i Entity Framework Core.

Oföränderlighet

En oföränderlig typ är en typ som hindrar dig från att ändra egenskaps- eller fältvärden för ett objekt när det har instansierats. Oföränderlighet kan vara användbart när du behöver en typ som är trådsäker eller om du är beroende av att en hashkod förblir densamma i en hash-tabell. Poster ger en koncis syntax för att skapa och arbeta med oföränderliga typer.

Oföränderlighet är inte lämpligt för alla datascenarier. Entity Framework Core stöder till exempel inte uppdatering med oföränderliga entitetstyper.

Hur poster skiljer sig från klasser och structs

Samma syntax som deklarerar och instansierar klasser eller structs kan användas med poster. Ersätt bara nyckelordet classrecordmed , eller använd record struct i stället för struct. På samma sätt stöds samma syntax för att uttrycka arvsrelationer av postklasser. Poster skiljer sig från klasser på följande sätt:

  • Du kan använda positionsparametrar i en primär konstruktor för att skapa och instansiera en typ med oföränderliga egenskaper.
  • Samma metoder och operatorer som anger referensjämlikhet eller olikhet i klasser (till exempel Object.Equals(Object) och ==), anger värdejämlikhet eller ojämlikhet i poster.
  • Du kan använda ett with uttryck för att skapa en kopia av ett oföränderligt objekt med nya värden i valda egenskaper.
  • En postmetod ToString skapar en formaterad sträng som visar ett objekts typnamn och namn och värden för alla dess offentliga egenskaper.
  • En post kan ärva från en annan post. En post kan inte ärva från en klass och en klass kan inte ärva från en post.

Poststrukturer skiljer sig från structs genom att kompilatorn syntetiserar metoderna för likhet och ToString. Kompilatorn syntetiserar en Deconstruct metod för positionella poststrukturer.

Kompilatorn syntetiserar en offentlig init-only-egenskap för varje primär konstruktorparameter i en record class. I en record structsyntetiserar kompilatorn en offentlig read-write-egenskap. Kompilatorn skapar inte egenskaper för primära konstruktorparametrar i class och struct typer som inte innehåller record modifierare.

Exempel

I följande exempel definieras en offentlig post som använder positionsparametrar för att deklarera och instansiera en post. Sedan skrivs typnamnet och egenskapsvärdena ut:


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

}

I följande exempel visas värdejämlikhet i poster:

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

I följande exempel visas hur du använder ett with uttryck för att kopiera ett oföränderligt objekt och ändra en av egenskaperna:

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

Mer information finns i Poster (C#-referens).

Språkspecifikation för C#

Mer information finns i C#-språkspecifikationen. Språkspecifikationen är den slutgiltiga källan för C#-syntax och -användning.