Rekordok (C#-referencia)

A módosítóval record olyan referenciatípust definiálhat, amely beépített funkciókat biztosít az adatok beágyazásához. A C# 10 lehetővé teszi, hogy a record class szintaxis szinonimaként egyértelműsítsen egy referenciatípust, és record struct hasonló funkcionalitású értéktípust definiáljon.

Amikor egy rekordon elsődleges konstruktort deklarál, a fordító nyilvános tulajdonságokat hoz létre az elsődleges konstruktor paramétereihez. A rekord elsődleges konstruktorparamétereit pozícióparamétereknek nevezzük. A fordító olyan pozíciótulajdonságokat hoz létre, amelyek tükrözik az elsődleges konstruktort vagy a pozícióparamétereket. A fordító nem szintetizálja az elsődleges konstruktorparaméterek tulajdonságait olyan típusok esetében, amelyek nem rendelkeznek a record módosítóval.

Az alábbi két példa (vagy record class) referenciatípust mutat be record :

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

Az alábbi két példa az értéktípusokat mutatja be record struct :

public readonly record struct Point(double X, double Y, double Z);
public record struct Point
{
    public double X { get; init; }
    public double Y { get; init; }
    public double Z { get; init; }
}

A következő rekordokat is létrehozhatja mutable tulajdonságokkal és mezőkkel:

public record Person
{
    public required string FirstName { get; set; }
    public required string LastName { get; set; }
};

A rekordstruktúra is módosítható, mind a pozicionálási, mind a rekordstruktúra pozícióparaméterek nélkül:

public record struct DataMeasurement(DateTime TakenAt, double Measurement);
public record struct Point
{
    public double X { get; set; }
    public double Y { get; set; }
    public double Z { get; set; }
}

Bár a rekordok módosíthatók, elsősorban nem módosítható adatmodellek támogatására szolgálnak. A rekordtípus a következő funkciókat kínálja:

Az előző példák néhány különbséget mutatnak a hivatkozási típusok és az érték típusú rekordok között:

  • A record vagy egy record class deklarál egy referenciatípust. A class kulcsszó nem kötelező, de érthetőbbé teheti az olvasókat. Egy record struct értéktípust deklarál.
  • A pozíciótulajdonságok nem módosíthatók az a record class és a readonly record struct. Egy .record struct

A cikk további része mind a típusokat, mind a típusokat record classrecord struct ismerteti. A különbségek részletesek az egyes szakaszokban. Az a és egy record struct közötti döntéshez class hasonló és hasonló döntés között kell dönteniestruct.record class A kifejezésrekord az összes rekordtípusra vonatkozó viselkedés leírására szolgál. record class Vagy record struct olyan viselkedés leírására szolgál, amely csak a strustruktúra- vagy osztálytípusokra vonatkozik. A record struct típus a C# 10-ben lett bevezetve.

Tulajdonságdefiníció pozíciószintaxisa

A helymeghatározó paraméterekkel deklarálhatja egy rekord tulajdonságait, és inicializálhatja a tulajdonságértékeket egy példány létrehozásakor:

public record Person(string FirstName, string LastName);

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

Ha a tulajdonságdefiníció pozíciószintaxisát használja, a fordító a következőket hozza létre:

  • A rekorddeklarációban megadott minden egyes pozícióparaméterhez tartozó nyilvános automatikus tulajdonság.
    • Típusok és típusok eseténrecord: Csak init-only tulajdonság.readonly record struct
    • Típusok esetén record struct : Írásvédett tulajdonság.
  • Elsődleges konstruktor, amelynek paraméterei megegyeznek a rekorddeklarációban szereplő pozícióparaméterekkel.
  • Rekordstruktúratípusok esetén egy paraméter nélküli konstruktor, amely az egyes mezőket az alapértelmezett értékre állítja.
  • A Deconstruct rekorddeklarációban megadott minden egyes pozícióparaméter paraméterével rendelkező out metódus. A metódus a pozíciószintaxissal definiált tulajdonságokat dekonstruálja; figyelmen kívül hagyja a standard tulajdonságszintaxissal definiált tulajdonságokat.

Érdemes lehet attribútumokat hozzáadni ezekhez az elemekhez, amelyeket a fordító a rekorddefinícióból hoz létre. A pozíciórekord tulajdonságaira alkalmazott bármely attribútumhoz hozzáadhat célhelyet . Az alábbi példa a System.Text.Json.Serialization.JsonPropertyNameAttribute rekord minden tulajdonságára Person vonatkozik. A property: cél azt jelzi, hogy az attribútum a fordító által létrehozott tulajdonságra lesz alkalmazva. Más értékek az field: attribútum alkalmazása a mezőre, és param: az attribútum alkalmazása a paraméterre.

/// <summary>
/// Person record type
/// </summary>
/// <param name="FirstName">First Name</param>
/// <param name="LastName">Last Name</param>
/// <remarks>
/// The person type is a positional record containing the
/// properties for the first and last name. Those properties
/// map to the JSON elements "firstName" and "lastName" when
/// serialized or deserialized.
/// </remarks>
public record Person([property: JsonPropertyName("firstName")] string FirstName, 
    [property: JsonPropertyName("lastName")] string LastName);

Az előző példa azt is bemutatja, hogyan hozhat létre XML-dokumentációs megjegyzéseket a rekordhoz. A címkét hozzáadhatja az <param> elsődleges konstruktor paramétereinek dokumentációjának hozzáadásához.

Ha az automatikusan létrehozott tulajdonságdefiníció nem az, amit szeretne, azonos nevű saját tulajdonságot is definiálhat. Előfordulhat például, hogy módosítani szeretné az akadálymentességet vagy a módosíthatóságot, vagy implementációt szeretne biztosítani a tartozékhoz vagy set a get tartozékhoz. Ha a tulajdonságot a forrásban deklarálja, inicializálnia kell azt a rekord pozícióparaméteréből. Ha a tulajdonság autoimplementált tulajdonság, inicializálnia kell a tulajdonságot. Ha egy háttérmezőt ad hozzá a forráshoz, inicializálnia kell a háttérmezőt. A létrehozott dekonstruktor a tulajdonságdefiníciót használja. Az alábbi példa például egy pozíciórekord publictulajdonságait deklarálja LastNameFirstName, de a pozícióparamétert a Id következőre internalkorlátozza. Ezt a szintaxist rekordokhoz és rekordstruktúratípusokhoz használhatja.

public record Person(string FirstName, string LastName, string Id)
{
    internal string Id { get; init; } = Id;
}

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

}

A rekordtípusoknak nem kell helytulajdonságokat deklarálniuk. A rekordokat pozíciótulajdonságok nélkül deklarálhatja, és deklarálhat más mezőket és tulajdonságokat is, ahogyan az alábbi példában is látható:

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

Ha a tulajdonságokat standard tulajdonságszintaxissal definiálja, de kihagyja a hozzáférési módosító használatát, a tulajdonságok implicit módon privatelesznek.

Módosíthatatlanság

A pozíciórekord és a pozícióalapú írásvédett rekord a csak init-only tulajdonságok deklarálására utasítja . A pozicionált rekordstruktúra írási-olvasási tulajdonságokat deklarál. Felülbírálhatja bármelyik alapértelmezett beállítást, ahogy az előző szakaszban is látható.

A nem módosíthatóság akkor lehet hasznos, ha adatközpontú típusra van szükség a szálbiztosság érdekében, vagy ha egy kivonatkód ugyanaz marad a kivonattáblában. A nem módosíthatóság azonban nem minden adatforgatókönyv esetében megfelelő. Az Entity Framework Core például nem támogatja a nem módosítható entitástípusok frissítését.

A csak init-only tulajdonságok, függetlenül attól, hogy a pozícióparaméterekből (record classés readonly record struct) vagy a tartozékok megadásával init lettek létrehozva, sekély megváltoztathatatlansággal rendelkeznek. Az inicializálás után nem módosíthatja az érték típusú tulajdonságok értékét vagy a referencia típusú tulajdonságok hivatkozását. A referencia típusú tulajdonság által hivatkozott adatok azonban módosíthatók. Az alábbi példa azt mutatja be, hogy egy referencia típusú nem módosítható tulajdonság (ebben az esetben egy tömb) tartalma nem módosítható:

public record Person(string FirstName, string LastName, string[] PhoneNumbers);

public static void Main()
{
    Person person = new("Nancy", "Davolio", new string[1] { "555-1234" });
    Console.WriteLine(person.PhoneNumbers[0]); // output: 555-1234

    person.PhoneNumbers[0] = "555-6789";
    Console.WriteLine(person.PhoneNumbers[0]); // output: 555-6789
}

A rekordtípusokra jellemző funkciókat fordító-szintetizált metódusok implementálják, és egyik módszer sem veszélyezteti az objektumállapot módosításával a megváltoztathatatlanságot. Ha nincs megadva, a rendszer létrehozza a szintetizált metódusokat a , record structés readonly record struct a deklarációkhozrecord.

Értékegyenlőség

Ha nem bírálja felül vagy cseréli le az egyenlőségi módszereket, a deklarált típus szabályozza az egyenlőség definícióját:

  • A típusok esetében class két objektum egyenlő, ha ugyanarra az objektumra hivatkoznak a memóriában.
  • A típusok esetében struct két objektum egyenlő, ha azonos típusúak, és ugyanazokat az értékeket tárolják.
  • A módosítóval (record classés record structreadonly record struct) rendelkező record típusok esetében két objektum egyenlő, ha azonos típusúak, és ugyanazokat az értékeket tárolják.

Az egyenlőség record struct definíciója megegyezik structa . A különbség az, hogy egy struct, a megvalósítás van, ValueType.Equals(Object) és támaszkodik tükröződés. A rekordok esetében a implementáció szintetizált fordító, és a deklarált adattagokat használja.

Egyes adatmodellekhez referenciaegyenlőség szükséges. Az Entity Framework Core például a referenciaegyenlőségtől függ annak biztosítása érdekében, hogy egy entitástípusnak csak egy példányát használja az egy elméletileg egy entitáshoz. Emiatt a rekordok és a rekordstruktúra nem megfelelő entitástípusokként való használatra az Entity Framework Core-ban.

Az alábbi példa a rekordtípusok értékegyenlőségét szemlélteti:

public record Person(string FirstName, string LastName, string[] PhoneNumbers);

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
}

Az értékegyenlőség megvalósítása érdekében a fordító több módszert szintetizál, többek között a következőket:

  • A Object.Equals(Object)felülbírálása. Hiba, ha a felülbírálás explicit módon van deklarálva.

    Ez a módszer a statikus módszer alapja Object.Equals(Object, Object) , ha mindkét paraméter nem null értékű.

  • A virtual, vagy sealed, Equals(R? other) ahol R a rekord típusa. Ez a metódus implementálja a IEquatable<T>. Ez a módszer explicit módon deklarálható.

  • Ha a rekordtípus egy alaprekordtípusból Baseszármazik, Equals(Base? other)akkor . Hiba, ha a felülbírálás explicit módon van deklarálva. Ha a saját implementációját Equals(R? other)adja meg, adja meg a megvalósítást GetHashCode is.

  • A Object.GetHashCode()felülbírálása. Ez a módszer explicit módon deklarálható.

  • Operátorok == felülbírálása és !=. Hiba, ha az operátorok explicit módon vannak deklarálva.

  • Ha a rekordtípus egy alaprekordtípusból származik, protected override Type EqualityContract { get; };akkor. Ez a tulajdonság explicit módon deklarálható. További információ: Egyenlőség az öröklési hierarchiákban.

A fordító nem szintetizál metódust, ha egy rekordtípus olyan metódussal rendelkezik, amely megfelel egy explicit módon deklarálható szintetizált metódus aláírásának.

Nem strukturált mutáció

Ha módosításokkal kell másolnia egy példányt, egy kifejezéssel with nem strukturált mutációt érhet el. Egy with kifejezés létrehoz egy új rekordpéldányt, amely egy meglévő rekordpéldány másolata, a megadott tulajdonságokkal és mezőkkel együtt. Az objektum inicializáló szintaxisával adja meg a módosítani kívánt értékeket, ahogy az alábbi példában is látható:

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

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
}

A with kifejezés beállíthat pozíciótulajdonságokat vagy standard tulajdonságszintaxissal létrehozott tulajdonságokat. A explicit módon deklarált tulajdonságoknak egy kifejezésben módosítani kell egy init vagy set több tartozékot with .

A kifejezés eredménye with egy sekély másolat, ami azt jelenti, hogy egy referenciatulajdonság esetében csak a példányra mutató hivatkozás lesz másolva. Az eredeti rekord és a másolat is ugyanarra a példányra mutató hivatkozással végződik.

A szolgáltatás típusokhoz való record class implementálásához a fordító egy klónozási módszert és egy másolási konstruktort szintetizál. A virtuális klónozási módszer egy új rekordot ad vissza, amelyet a másolási konstruktor inicializált. Kifejezés használatakor a fordító létrehoz egy with kódot, amely meghívja a klónozási metódust, majd beállítja a with kifejezésben megadott tulajdonságokat.

Ha más másolási viselkedésre van szüksége, saját példánykonstruktort írhat egy record class. Ha ezt teszi, a fordító nem szintetizál egyet. Állítsa be a konstruktort private , ha a rekord az sealed, ellenkező esetben készítse el protected. A fordító nem szintetizálja a példánykonstruktort a típusok esetében record struct . Írhat egyet, de a fordító nem generál rá hívásokat kifejezésekhez with . A program kimásolja a record struct hozzárendelés értékeit.

Nem bírálhatja felül a klónozási módszert, és nem hozhat létre semmilyen rekordtípusban elnevezett Clone tagot. A klónozási módszer tényleges neve fordító által generált.

Beépített formázás a megjelenítéshez

A rekordtípusok egy fordító által létrehozott ToString metódussal rendelkeznek, amely megjeleníti a nyilvános tulajdonságok és mezők nevét és értékeit. A ToString metódus a következő formátumú sztringet adja vissza:

<rekordtípus neve> { <tulajdonság neve> = <érték>, <tulajdonságnév> = <érték>, ...}

A kinyomtatott sztring <value> a tulajdonság típusának visszaadott sztringje ToString() . Az alábbi példában ChildNames egy System.Array, ahol ToString a következőt adja System.String[]vissza:

Person { FirstName = Nancy, LastName = Davolio, ChildNames = System.String[] }

A funkció implementálásához a fordító típusokban record class szintetizál egy virtuális PrintMembers metódust és egy felülbírálást ToString . Típusok esetén record struct ez a tag a private. A ToString felülbírálás létrehoz egy StringBuilder objektumot a típusnévvel, amelyet egy nyitó zárójel követ. Meghívja PrintMembers a tulajdonságnevek és értékek hozzáadását, majd hozzáadja a záró zárójelet. Az alábbi példa a szintetizált felülbíráláshoz hasonló kódot mutat be:

public override string ToString()
{
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.Append("Teacher"); // type name
    stringBuilder.Append(" { ");
    if (PrintMembers(stringBuilder))
    {
        stringBuilder.Append(" ");
    }
    stringBuilder.Append("}");
    return stringBuilder.ToString();
}

Saját implementációt PrintMembers vagy felülbírálást ToString is megadhat. Példákat a cikk későbbi részében, a PrintMembers származtatott rekordok szakaszában talál. A C# 10-ben és újabb verzióiban előfordulhat, hogy a sealed módosító implementációja ToString megakadályozza, hogy a fordító bármilyen származtatott rekord implementációját szintetizáljaToString. A típusok hierarchiája record során konzisztens sztring-reprezentációt hozhat létre. (A származtatott rekordokban továbbra is létre van hozva egy PrintMembers metódus az összes származtatott tulajdonsághoz.)

Öröklődés

Ez a szakasz csak a típusokra record class vonatkozik.

Egy rekord örökölhet egy másik rekordot. Egy rekord azonban nem örökölhető egy osztálytól, és az osztály nem örökölhet rekordból.

Pozícióparaméterek származtatott rekordtípusokban

A származtatott rekord az alaprekord elsődleges konstruktorának összes paraméteréhez deklarálja a pozícióparamétereket. Az alaprekord deklarálja és inicializálja ezeket a tulajdonságokat. A származtatott rekord nem rejti el őket, csak az alaprekordban nem deklarált paraméterek tulajdonságait hozza létre és inicializálja.

Az alábbi példa a pozíciótulajdonság szintaxisával szemlélteti az öröklést:

public abstract record Person(string FirstName, string LastName);
public record Teacher(string FirstName, string LastName, int Grade)
    : Person(FirstName, LastName);
public static void Main()
{
    Person teacher = new Teacher("Nancy", "Davolio", 3);
    Console.WriteLine(teacher);
    // output: Teacher { FirstName = Nancy, LastName = Davolio, Grade = 3 }
}

Egyenlőség az öröklési hierarchiákban

Ez a szakasz a típusokra record class vonatkozik, a típusokra azonban nem record struct . Ahhoz, hogy két rekordváltozó egyenlő legyen, a futási idő típusának egyenlőnek kell lennie. A változók típusai eltérőek lehetnek. Az örökölt egyenlőség összehasonlítását az alábbi példakód szemlélteti:

public abstract record Person(string FirstName, string LastName);
public record Teacher(string FirstName, string LastName, int Grade)
    : Person(FirstName, LastName);
public record Student(string FirstName, string LastName, int Grade)
    : Person(FirstName, LastName);
public static void Main()
{
    Person teacher = new Teacher("Nancy", "Davolio", 3);
    Person student = new Student("Nancy", "Davolio", 3);
    Console.WriteLine(teacher == student); // output: False

    Student student2 = new Student("Nancy", "Davolio", 3);
    Console.WriteLine(student2 == student); // output: True
}

A példában minden változó deklarálva Personvan, még akkor is, ha a példány egy vagy több származtatott típusTeacherStudent. A példányok ugyanazokkal a tulajdonságokkal és tulajdonságértékekkel rendelkeznek. De student == teacher mindkettő PersonFalse -típusú változó, és student == student2 visszaadjaTrue, bár az Person egyik változó, a másik pedig változóStudent. Az egyenlőségi teszt a tényleges objektum futásidejű típusától függ, nem a változó deklarált típusától.

Ennek a viselkedésnek a megvalósítása érdekében a fordító szintetizál egy EqualityContract tulajdonságot, amely egy Type olyan objektumot ad vissza, amely megfelel a rekord típusának. Ez EqualityContract lehetővé teszi, hogy az egyenlőségi metódusok összehasonlítsák az objektumok futásidejű típusát, amikor egyenlőséget keresnek. Ha egy rekord alaptípusa , objectakkor ez a tulajdonság .virtual Ha az alaptípus egy másik rekordtípus, ez a tulajdonság felülbírálás. Ha a rekord típusa az sealed, akkor ez a tulajdonság gyakorlatilag sealed azért van, mert a típus az sealed.

Ha a kód egy származtatott típus két példányát hasonlítja össze, a szintetizált egyenlőségi módszerek ellenőrzik az alap és a származtatott típusok összes adattagját az egyenlőség szempontjából. A szintetizált GetHashCode metódus az alaptípusban és a GetHashCode származtatott rekordtípusban deklarált összes adattag metódusát használja. Az adattagok tartalmazzák az record összes deklarált mezőt és a fordító által szintetizált háttérmezőt az automatikusan létrehozott tulajdonságokhoz.

with kifejezések származtatott rekordokban

A kifejezés eredménye with ugyanazzal a futásidejű típussal rendelkezik, mint a kifejezés operandusa. A futtatási idő típusának összes tulajdonsága másolásra kerül, de csak a fordítási idő típusú tulajdonságok állíthatók be, ahogyan az alábbi példa mutatja:

public record Point(int X, int Y)
{
    public int Zbase { get; set; }
};
public record NamedPoint(string Name, int X, int Y) : Point(X, Y)
{
    public int Zderived { get; set; }
};

public static void Main()
{
    Point p1 = new NamedPoint("A", 1, 2) { Zbase = 3, Zderived = 4 };

    Point p2 = p1 with { X = 5, Y = 6, Zbase = 7 }; // Can't set Name or Zderived
    Console.WriteLine(p2 is NamedPoint);  // output: True
    Console.WriteLine(p2);
    // output: NamedPoint { X = 5, Y = 6, Zbase = 7, Name = A, Zderived = 4 }

    Point p3 = (NamedPoint)p1 with { Name = "B", X = 5, Y = 6, Zbase = 7, Zderived = 8 };
    Console.WriteLine(p3);
    // output: NamedPoint { X = 5, Y = 6, Zbase = 7, Name = B, Zderived = 8 }
}

PrintMembers formázás származtatott rekordokban

A származtatott rekordtípus szintetizált PrintMembers metódusa meghívja az alap implementációt. Az eredmény az, hogy a kimenet tartalmazza ToString a származtatott és az alaptípusú összes nyilvános tulajdonságot és mezőt, ahogyan az az alábbi példában látható:

public abstract record Person(string FirstName, string LastName);
public record Teacher(string FirstName, string LastName, int Grade)
    : Person(FirstName, LastName);
public record Student(string FirstName, string LastName, int Grade)
    : Person(FirstName, LastName);

public static void Main()
{
    Person teacher = new Teacher("Nancy", "Davolio", 3);
    Console.WriteLine(teacher);
    // output: Teacher { FirstName = Nancy, LastName = Davolio, Grade = 3 }
}

A metódus saját implementációját PrintMembers is megadhatja. Ha így tesz, használja a következő aláírást:

  • sealed Olyan rekord esetében, amely származik object (nem deklarál alaprekordot): private bool PrintMembers(StringBuilder builder);
  • Egy sealed másik rekordból származó rekord esetében (vegye figyelembe, hogy a beágyazási típus sealedaz, tehát a módszer hatékonyan sealed): protected override bool PrintMembers(StringBuilder builder);
  • Olyan rekord esetén, amely nem sealed objektumból származik: protected virtual bool PrintMembers(StringBuilder builder);
  • Olyan rekord esetén, amely nem sealed egy másik rekordból származik: protected override bool PrintMembers(StringBuilder builder);

Íme egy példa a szintetizált PrintMembers metódusokat lecserélő kódra, az egyik az objektumból származó rekordtípusra, a másik pedig egy másik rekordból származó rekordtípusra:

public abstract record Person(string FirstName, string LastName, string[] PhoneNumbers)
{
    protected virtual bool PrintMembers(StringBuilder stringBuilder)
    {
        stringBuilder.Append($"FirstName = {FirstName}, LastName = {LastName}, ");
        stringBuilder.Append($"PhoneNumber1 = {PhoneNumbers[0]}, PhoneNumber2 = {PhoneNumbers[1]}");
        return true;
    }
}

public record Teacher(string FirstName, string LastName, string[] PhoneNumbers, int Grade)
    : Person(FirstName, LastName, PhoneNumbers)
{
    protected override bool PrintMembers(StringBuilder stringBuilder)
    {
        if (base.PrintMembers(stringBuilder))
        {
            stringBuilder.Append(", ");
        };
        stringBuilder.Append($"Grade = {Grade}");
        return true;
    }
};

public static void Main()
{
    Person teacher = new Teacher("Nancy", "Davolio", new string[2] { "555-1234", "555-6789" }, 3);
    Console.WriteLine(teacher);
    // output: Teacher { FirstName = Nancy, LastName = Davolio, PhoneNumber1 = 555-1234, PhoneNumber2 = 555-6789, Grade = 3 }
}

Feljegyzés

A C# 10-es és újabb verzióiban a fordító származtatott rekordokban szintetizál PrintMembers , még akkor is, ha egy alaprekord lezárta a metódust ToString . A saját implementációját is létrehozhatja PrintMembers.

Dekonstruktor viselkedése származtatott rekordokban

A Deconstruct származtatott rekord metódusa a fordítási idő típusú összes pozíciótulajdonság értékét adja vissza. Ha a változótípus alaprekord, csak az alaprekord tulajdonságai lesznek dekonstruálva, kivéve, ha az objektumot a származtatott típusra öntötték. Az alábbi példa egy dekonstruktor meghívását mutatja be egy származtatott rekordon.

public abstract record Person(string FirstName, string LastName);
public record Teacher(string FirstName, string LastName, int Grade)
    : Person(FirstName, LastName);
public record Student(string FirstName, string LastName, int Grade)
    : Person(FirstName, LastName);

public static void Main()
{
    Person teacher = new Teacher("Nancy", "Davolio", 3);
    var (firstName, lastName) = teacher; // Doesn't deconstruct Grade
    Console.WriteLine($"{firstName}, {lastName}");// output: Nancy, Davolio

    var (fName, lName, grade) = (Teacher)teacher;
    Console.WriteLine($"{fName}, {lName}, {grade}");// output: Nancy, Davolio, 3
}

Általános korlátozások

A record kulcsszó egy vagy struct több típus módosítójaclass. A record módosító hozzáadása magában foglalja a cikkben korábban ismertetett viselkedést. Nincs általános korlátozás, amely megköveteli, hogy egy típus rekord legyen. Az A record class megfelel a kényszernek class . Az A record struct megfelel a kényszernek struct . További információ: Típusparaméterek korlátozásai.

C# nyelvspecifikáció

További információkért lásd a C#-nyelv specifikációjának Osztályok szakaszát.

További információ ezekről a funkciókról:

Lásd még