KayıtlarRecords

Bu teklif, C# dil tasarımı ekibi tarafından kabul edilen C# 9 kayıtları özelliğinin belirtimini izler.This proposal tracks the specification for the C# 9 records feature, as agreed to by the C# language design team.

Bir kayıt için sözdizimi aşağıdaki gibidir:The syntax for a record is as follows:

record_declaration
    : attributes? class_modifier* 'partial'? 'record' identifier type_parameter_list?
      parameter_list? record_base? type_parameter_constraints_clause* record_body
    ;

record_base
    : ':' class_type argument_list?
    | ':' interface_type_list
    | ':' class_type argument_list? ',' interface_type_list
    ;

record_body
    : '{' class_member_declaration* '}' ';'?
    | ';'
    ;

Kayıt türleri, sınıf bildirimine benzer başvuru türleridir.Record types are reference types, similar to a class declaration. Bir kaydın bir içermesi halinde bir kayıt olması hatadır record_base argument_list record_declaration parameter_list .It is an error for a record to provide a record_base argument_list if the record_declaration does not contain a parameter_list. Kısmi bir kaydın en çok bir kısmi tür bildirimi, bir sağlayabilir parameter_list .At most one partial type declaration of a partial record may provide a parameter_list.

Kayıt parametreleri ref out veya this değiştiricilerini kullanamaz (ancak in ve params izin verilir).Record parameters cannot use ref, out or this modifiers (but in and params are allowed).

DevralmaInheritance

, Sınıf olmadığı object ve sınıfların kayıtlardan devralması gerekmedikçe kayıtlar sınıflardan devralınabilir.Records cannot inherit from classes, unless the class is object, and classes cannot inherit from records. Kayıtlar, diğer kayıtlardan devralınabilir.Records can inherit from other records.

Bir kayıt türünün üyeleriMembers of a record type

Kayıt gövdesinde belirtilen üyelere ek olarak, bir kayıt türünün ek birleştirilmiş üyeleri vardır.In addition to the members declared in the record body, a record type has additional synthesized members. "Eşleşen" imza içeren bir üye, kayıt gövdesinde veya "eşleşen" imza ile erişilebilir bir somut sanal olmayan üye olarak bildirilirse, Üyeler sentezleştirilir.Members are synthesized unless a member with a "matching" signature is declared in the record body or an accessible concrete non-virtual member with a "matching" signature is inherited. İki üye, aynı imzaya sahip olmaları veya devralma senaryosunda "gizlemenin" kabul edilmesi halinde eşleşen kabul edilir.Two members are considered matching if they have the same signature or would be considered "hiding" in an inheritance scenario. Bir kaydın bir üyesinin "kopya" olarak adlandırılması hatadır.It is an error for a member of a record to be named "Clone". Bir kaydın örnek alanının güvenli olmayan bir türe sahip olması hatadır.It is an error for an instance field of a record to have an unsafe type.

Birleştirilmemiş Üyeler şunlardır:The synthesized members are as follows:

Eşitlik üyeleriEquality members

Kayıt öğesinden türetildiyse object , kayıt türü aşağıdaki şekilde tanımlanan bir özelliğe eşdeğer bir sentezlenmiş ReadOnly özelliği içerir:If the record is derived from object, the record type includes a synthesized readonly property equivalent to a property declared as follows:

Type EqualityContract { get; };

Özelliği, private kayıt türü ise olur sealed .The property is private if the record type is sealed. Aksi halde, özelliği virtual ve olur protected .Otherwise, the property is virtual and protected. Özelliği açıkça bildirilebilecek.The property can be declared explicitly. Açık bildirimin beklenen imzayla veya erişilebilirlikle eşleşmemesi veya açık bildirimin türetilmiş bir türde geçersiz kılmaya izin vermiyorsa ve kayıt türü değilse, bu bir hatadır sealed .It is an error if the explicit declaration does not match the expected signature or accessibility, or if the explicit declaration doesn't allow overriding it in a derived type and the record type is not sealed.

Kayıt türü bir temel kayıt türünden türetildiyse Base , kayıt türü aşağıdaki şekilde tanımlanan bir özelliğe eşdeğer bir sentezlenmiş ReadOnly özelliği içerir:If the record type is derived from a base record type Base, the record type includes a synthesized readonly property equivalent to a property declared as follows:

protected override Type EqualityContract { get; };

Özelliği açıkça bildirilebilecek.The property can be declared explicitly. Açık bildirimin beklenen imzayla veya erişilebilirlikle eşleşmemesi veya açık bildirimin türetilmiş bir türde geçersiz kılmaya izin vermiyorsa ve kayıt türü değilse, bu bir hatadır sealed .It is an error if the explicit declaration does not match the expected signature or accessibility, or if the explicit declaration doesn't allow overriding it in a derived type and the record type is not sealed. Sentezleştirilmiş veya açıkça tanımlanmış bir özellik, kayıt türünde bu imzaya sahip bir özelliği geçersiz kılmazsa Base (örneğin, özellik, Base veya korumalı, ancak sanal, vb.), bu bir hatadır.It is an error if either synthesized, or explicitly declared property doesn't override a property with this signature in the record type Base (for example, if the property is missing in the Base, or sealed, or not virtual, etc.). Sentezlenmiş özellik, typeof(R) R kayıt türü olan ' i döndürür.The synthesized property returns typeof(R) where R is the record type.

Kayıt türü uygular System.IEquatable<R> ve ' nin, kayıt türü olduğu yerde, kesin türü belirtilmiş bir aşırı yüklemesi içerir Equals(R? other) R .The record type implements System.IEquatable<R> and includes a synthesized strongly-typed overload of Equals(R? other) where R is the record type. Yöntemi public , ve virtual kayıt türü olmadığı müddetçe yöntemi olur sealed .The method is public, and the method is virtual unless the record type is sealed. Yöntemi açıkça bildirilebilecek.The method can be declared explicitly. Açık bildirimin beklenen imza veya erişilebilirlikle eşleşmemesi ya da açık bildirimi türetilmiş bir türde geçersiz kılmaya izin vermiyorsa ve kayıt türü değilse, bu bir hatadır sealed .It is an error if the explicit declaration does not match the expected signature or accessibility, or the explicit declaration doesn't allow overriding it in a derived type and the record type is not sealed.

Equals(R? other)Kullanıcı tanımlı (birleştirilmemiş) ise, ancak yoksa GetHashCode , bir uyarı üretilir.If Equals(R? other) is user-defined (not synthesized) but GetHashCode is not, a warning is produced.

public virtual bool Equals(R? other);

Equals(R?) true Sentezler yalnızca aşağıdakilerin her biri ise true :The synthesized Equals(R?) returns true if and only if each of the following are true:

  • other değildir null veother is not null, and
  • fieldNDevralınmayan kayıt türündeki her bir örnek alanı için, System.Collections.Generic.EqualityComparer<TN>.Default.Equals(fieldN, other.fieldN) TN alan türü veFor each instance field fieldN in the record type that is not inherited, the value of System.Collections.Generic.EqualityComparer<TN>.Default.Equals(fieldN, other.fieldN) where TN is the field type, and
  • Bir temel kayıt türü varsa, değeri base.Equals(other) (sanal olmayan bir çağrı public virtual bool Equals(Base? other) ); Aksi takdirde değeri EqualityContract == other.EqualityContract .If there is a base record type, the value of base.Equals(other) (a non-virtual call to public virtual bool Equals(Base? other)); otherwise the value of EqualityContract == other.EqualityContract.

Kayıt türü, == != aşağıdaki gibi belirtilen işleçlere eşdeğer ve birleştirilmiş işleçleri içerir:The record type includes synthesized == and != operators equivalent to operators declared as follows:

public static bool operator==(R? left, R? right)
    => (object)left == right || (left?.Equals(right) ?? false);
public static bool operator!=(R? left, R? right)
    => !(left == right);

Equalsİşleci tarafından çağrılan yöntem == Equals(R? other) yukarıda belirtilen yöntemdir.The Equals method called by the == operator is the Equals(R? other) method specified above. !=İşleci işlecine devreder == .The != operator delegates to the == operator. İşleçler açıkça bildirilirse, bu bir hatadır.It is an error if the operators are declared explicitly.

Kayıt türü bir temel kayıt türünden türetildiyse Base , kayıt türü aşağıdaki şekilde belirtilen bir yönteme eşdeğer bir sentezlenmiş geçersiz kılma içerir:If the record type is derived from a base record type Base, the record type includes a synthesized override equivalent to a method declared as follows:

public sealed override bool Equals(Base? other);

Geçersiz kılma açıkça bildirilirse, bu bir hatadır.It is an error if the override is declared explicitly. Yöntem, kayıt türünde aynı imzaya sahip bir yöntemi geçersiz kılmazsa Base (örneğin, yöntemi, Base veya korumalı ya da sanal değilse, vb.), bu bir hatadır.It is an error if the method doesn't override a method with same signature in record type Base (for example, if the method is missing in the Base, or sealed, or not virtual, etc.). Sentezlenmiş geçersiz kılma döndürüyor Equals((object?)other) .The synthesized override returns Equals((object?)other).

Kayıt türü, aşağıdaki şekilde belirtilen bir yönteme eşdeğer bir sentezlenmiş geçersiz kılma içerir:The record type includes a synthesized override equivalent to a method declared as follows:

public override bool Equals(object? obj);

Geçersiz kılma açıkça bildirilirse, bu bir hatadır.It is an error if the override is declared explicitly. Yöntem geçersiz kılınmazsa object.Equals(object? obj) (örneğin, ara taban türlerinde gölgeleme nedeniyle, vb.) bir hatadır.It is an error if the method doesn't override object.Equals(object? obj) (for example, due to shadowing in intermediate base types, etc.). Sentezlenmiş geçersiz kılma Equals(other as R) , R kayıt türü olduğunu döndürür.The synthesized override returns Equals(other as R) where R is the record type.

Kayıt türü, aşağıdaki şekilde belirtilen bir yönteme eşdeğer bir sentezlenmiş geçersiz kılma içerir:The record type includes a synthesized override equivalent to a method declared as follows:

public override int GetHashCode();

Yöntemi açıkça bildirilebilecek.The method can be declared explicitly. Açık bildirimin türetilmiş bir türde geçersiz kılınma izni yoksa ve kayıt türü değilse, bu bir hatadır sealed .It is an error if the explicit declaration doesn't allow overriding it in a derived type and the record type is not sealed. Sentezlenmiş veya açıkça tanımlanmış yöntemin geçersiz kılınmadığı bir hatadır object.GetHashCode() (örneğin, ara taban türlerinde gölgeleme nedeniyle, vb.).It is an error if either synthesized, or explicitly declared method doesn't override object.GetHashCode() (for example, due to shadowing in intermediate base types, etc.).

Aşağıdakilerden biri açık Equals(R?) GetHashCode() olarak bildirilirse ancak diğer yöntem açık değilse bir uyarı bildirilir.A warning is reported if one of Equals(R?) and GetHashCode() is explicitly declared but the other method is not explicit.

Sentezlenmiş geçersiz kılma, GetHashCode() int aşağıdaki değerleri birleştirmenin sonucunu döndürür:The synthesized override of GetHashCode() returns an int result of combining the following values:

  • fieldNDevralınmayan kayıt türündeki her bir örnek alanı için, System.Collections.Generic.EqualityComparer<TN>.Default.GetHashCode(fieldN) TN alan türü veFor each instance field fieldN in the record type that is not inherited, the value of System.Collections.Generic.EqualityComparer<TN>.Default.GetHashCode(fieldN) where TN is the field type, and
  • Bir temel kayıt türü varsa değeri base.GetHashCode() ; Aksi takdirde değeri System.Collections.Generic.EqualityComparer<System.Type>.Default.GetHashCode(EqualityContract) .If there is a base record type, the value of base.GetHashCode(); otherwise the value of System.Collections.Generic.EqualityComparer<System.Type>.Default.GetHashCode(EqualityContract).

Örneğin, aşağıdaki kayıt türlerini göz önünde bulundurun:For example, consider the following record types:

record R1(T1 P1);
record R2(T1 P1, T2 P2) : R1(P1);
record R3(T1 P1, T2 P2, T3 P3) : R2(P1, P2);

Bu kayıt türleri için, birleştirilmiş eşitlik üyeleri şöyle bir şey olacaktır:For those record types, the synthesized equality members would be something like:

class R1 : IEquatable<R1>
{
    public T1 P1 { get; init; }
    protected virtual Type EqualityContract => typeof(R1);
    public override bool Equals(object? obj) => Equals(obj as R1);
    public virtual bool Equals(R1? other)
    {
        return !(other is null) &&
            EqualityContract == other.EqualityContract &&
            EqualityComparer<T1>.Default.Equals(P1, other.P1);
    }
    public static bool operator==(R1? left, R1? right)
        => (object)left == right || (left?.Equals(right) ?? false);
    public static bool operator!=(R1? left, R1? right)
        => !(left == right);
    public override int GetHashCode()
    {
        return Combine(EqualityComparer<Type>.Default.GetHashCode(EqualityContract),
            EqualityComparer<T1>.Default.GetHashCode(P1));
    }
}

class R2 : R1, IEquatable<R2>
{
    public T2 P2 { get; init; }
    protected override Type EqualityContract => typeof(R2);
    public override bool Equals(object? obj) => Equals(obj as R2);
    public sealed override bool Equals(R1? other) => Equals((object?)other);
    public virtual bool Equals(R2? other)
    {
        return base.Equals((R1?)other) &&
            EqualityComparer<T2>.Default.Equals(P2, other.P2);
    }
    public static bool operator==(R2? left, R2? right)
        => (object)left == right || (left?.Equals(right) ?? false);
    public static bool operator!=(R2? left, R2? right)
        => !(left == right);
    public override int GetHashCode()
    {
        return Combine(base.GetHashCode(),
            EqualityComparer<T2>.Default.GetHashCode(P2));
    }
}

class R3 : R2, IEquatable<R3>
{
    public T3 P3 { get; init; }
    protected override Type EqualityContract => typeof(R3);
    public override bool Equals(object? obj) => Equals(obj as R3);
    public sealed override bool Equals(R2? other) => Equals((object?)other);
    public virtual bool Equals(R3? other)
    {
        return base.Equals((R2?)other) &&
            EqualityComparer<T3>.Default.Equals(P3, other.P3);
    }
    public static bool operator==(R3? left, R3? right)
        => (object)left == right || (left?.Equals(right) ?? false);
    public static bool operator!=(R3? left, R3? right)
        => !(left == right);
    public override int GetHashCode()
    {
        return Combine(base.GetHashCode(),
            EqualityComparer<T3>.Default.GetHashCode(P3));
    }
}

Üyeleri Kopyala ve KopyalaCopy and Clone members

Kayıt türü iki kopyalama üyesini içerir:A record type contains two copying members:

  • Kayıt türünün tek bir bağımsız değişkenini alan Oluşturucu.A constructor taking a single argument of the record type. "Kopya Oluşturucu" olarak adlandırılır.It is referred to as a "copy constructor".
  • Derleyici ile ayrılmış bir ada sahip bir sentezlenmiş Ortak parametresiz örnek "kopya" yöntemiA synthesized public parameterless instance "clone" method with a compiler-reserved name

Kopya oluşturucunun amacı, parametreyi parametresinden oluşturulan yeni örneğe kopyalamadır.The purpose of the copy constructor is to copy the state from the parameter to the new instance being created. Bu Oluşturucu, kayıt bildiriminde bulunan hiçbir örnek alanı/özellik başlatıcısının hiçbirini çalıştırmaz.This constructor doesn't run any instance field/property initializers present in the record declaration. Oluşturucu açıkça bildirilirse, derleyici tarafından bir Oluşturucu birleştirilmiştir.If the constructor is not explicitly declared, a constructor will be synthesized by the compiler. Kayıt mühürlense, Oluşturucu özel olur, aksi takdirde korunacaktır.If the record is sealed, the constructor will be private, otherwise it will be protected. Açık olarak tanımlanmış bir kopya Oluşturucusu, kayıt mühürlenmediği takdirde ortak veya korumalı olmalıdır.An explicitly declared copy constructor must be either public or protected, unless the record is sealed. Oluşturucunun yapması gereken ilk şey, temel bir kopya Oluşturucu ya da kayıt nesneden devralırsa parametreye bir nesne Oluşturucu çağırmaktır.The first thing the constructor must do, is to call a copy constructor of the base, or a parameter-less object constructor if the record inherits from object. Kullanıcı tanımlı bir kopya Oluşturucusu, bu gereksinimi yerine getirmeyen örtük veya açık bir Oluşturucu başlatıcısı kullanıyorsa bir hata bildirilir.An error is reported if a user-defined copy constructor uses an implicit or explicit constructor initializer that doesn't fulfill this requirement. Bir temel kopya Oluşturucu çağrıldıktan sonra, birleştirilmiş bir kopya Oluşturucusu, kayıt türü içinde örtük veya açık olarak belirtilen tüm örnek alanları için değerleri kopyalar.After a base copy constructor is invoked, a synthesized copy constructor copies values for all instance fields implicitly or explicitly declared within the record type. Açık veya örtük olarak bir kopya oluşturucusunun tek olması, varsayılan örnek oluşturucusunun otomatik eklenmesini engellemez.The sole presence of a copy constructor, whether explicit or implicit, doesn't prevent an automatic addition of a default instance constructor.

Temel kayıtta bir sanal "kopya" yöntemi varsa, sentezlenmiş "kopya" yöntemi bunu geçersiz kılar ve yöntemin dönüş türü, "covaryant dönüşü" özelliği desteklense ve geçersiz kılma döndürme türü, aksi takdirde geçerli içeren türdür.If a virtual "clone" method is present in the base record, the synthesized "clone" method overrides it and the return type of the method is the current containing type if the "covariant returns" feature is supported and the override return type otherwise. Temel kayıt kopyalama yöntemi mühürlendiyse bir hata oluşturulur.An error is produced if the base record clone method is sealed. Temel kayıtta bir sanal "kopya" yöntemi yoksa, kopyalama yönteminin dönüş türü kapsayan tür olur ve kayıt korumalı veya soyut olmadığı takdirde yöntem sanal olur.If a virtual "clone" method is not present in the base record, the return type of the clone method is the containing type and the method is virtual, unless the record is sealed or abstract. İçerilen kayıt soyut ise, sentezlenmiş kopya yöntemi de soyuttur.If the containing record is abstract, the synthesized clone method is also abstract. "Clone" yöntemi soyut değilse, bir kopya Oluşturucusu çağrısının sonucunu döndürür.If the "clone" method is not abstract, it returns the result of a call to a copy constructor.

Yazdırma üyeleri: PrintMembers ve ToString yöntemleriPrinting members: PrintMembers and ToString methods

Kayıt öğesinden türetildiyse object , kayıt aşağıdaki şekilde belirtilen bir yönteme eşdeğer bir sentezlenmiş yöntem içerir:If the record is derived from object, the record includes a synthesized method equivalent to a method declared as follows:

bool PrintMembers(System.Text.StringBuilder builder);

Yöntemi, private kayıt türü ise olur sealed .The method is private if the record type is sealed. Aksi takdirde, yöntemi virtual ve olur protected .Otherwise, the method is virtual and protected.

Yöntemi:The method:

  1. kaydın yazdırılabilir üyelerinin her biri (statik olmayan ortak alan ve okunabilir Özellik üyeleri) için, bu üyenin adının ardından "=" işaretinden sonra üyenin değeri "," ile ayrılmış olarak ekler,for each of the record's printable members (non-static public field and readable property members), appends that member's name followed by " = " followed by the member's value separated with ", ",
  2. kayıtta yazdırılabilir Üyeler varsa, doğru döndürün.return true if the record has printable members.

Değer türü olan bir üye için, hedef platformun kullanabileceği en verimli yöntemi kullanarak değerini bir dize gösterimine dönüştürüyoruz.For a member that has a value type, we will convert its value to a string representation using the most efficient method available to the target platform. Bu, ' ToString ye geçirmeden önce çağırma anlamına gelir StringBuilder.Append .At present that means calling ToString before passing to StringBuilder.Append.

Kayıt türü bir temel kayıttan türetilirse Base , kayıt aşağıdaki şekilde belirtilen bir yönteme eşdeğer bir sentezlenmiş geçersiz kılma içerir:If the record type is derived from a base record Base, the record includes a synthesized override equivalent to a method declared as follows:

protected override bool PrintMembers(StringBuilder builder);

Kayıtta yazdırılabilir üye yoksa, yöntemi temel PrintMembers yöntemi bir bağımsız değişkenle ( builder parametresi) çağırır ve sonucu döndürür.If the record has no printable members, the method calls the base PrintMembers method with one argument (its builder parameter) and returns the result.

Aksi takdirde, yöntemi:Otherwise, the method:

  1. temel PrintMembers yöntemi bir bağımsız değişkenle ( builder parametresi) çağırır,calls the base PrintMembers method with one argument (its builder parameter),
  2. PrintMembersYöntem true olarak döndürülürse, oluşturucuya "," ekleyin,if the PrintMembers method returned true, append ", " to the builder,
  3. kaydın yazdırılabilir üyelerinin her biri için, bu üyenin adının ardından "=" işaretinden sonra üyenin değerini this.member (veya this.member.ToString() değer türleri için), "," ile ayırarak ekler.for each of the record's printable members, appends that member's name followed by " = " followed by the member's value: this.member (or this.member.ToString() for value types), separated with ", ",
  4. true döndürün.return true.

PrintMembersYöntemi açıkça bildirilebilecek.The PrintMembers method can be declared explicitly. Açık bildirimin beklenen imzayla veya erişilebilirlikle eşleşmemesi veya açık bildirimin türetilmiş bir türde geçersiz kılmaya izin vermiyorsa ve kayıt türü değilse, bu bir hatadır sealed .It is an error if the explicit declaration does not match the expected signature or accessibility, or if the explicit declaration doesn't allow overriding it in a derived type and the record type is not sealed.

Kayıt, aşağıdaki şekilde belirtilen bir yönteme eşdeğer bir sentezlenmiş yöntem içerir:The record includes a synthesized method equivalent to a method declared as follows:

public override string ToString();

Yöntemi açıkça bildirilebilecek.The method can be declared explicitly. Açık bildirimin beklenen imzayla veya erişilebilirlikle eşleşmemesi veya açık bildirimin türetilmiş bir türde geçersiz kılmaya izin vermiyorsa ve kayıt türü değilse, bu bir hatadır sealed .It is an error if the explicit declaration does not match the expected signature or accessibility, or if the explicit declaration doesn't allow overriding it in a derived type and the record type is not sealed. Sentezlenmiş veya açıkça tanımlanmış yöntemin geçersiz kılınmadığı bir hatadır object.ToString() (örneğin, ara taban türlerinde gölgeleme nedeniyle, vb.).It is an error if either synthesized, or explicitly declared method doesn't override object.ToString() (for example, due to shadowing in intermediate base types, etc.).

Sentezlenmiş Yöntem:The synthesized method:

  1. bir StringBuilder örnek oluşturur,creates a StringBuilder instance,
  2. kayıt adını oluşturucuya ekler ve ardından "{",appends the record name to the builder, followed by " { ",
  3. kayıt PrintMembers yöntemini, oluşturucuyu vererek, ardından "" true döndürülürse,invokes the record's PrintMembers method giving it the builder, followed by " " if it returned true,
  4. "}" ekler,appends "}",
  5. oluşturucunun içeriğini ile döndürür builder.ToString() .returns the builder's contents with builder.ToString().

Örneğin, aşağıdaki kayıt türlerini göz önünde bulundurun:For example, consider the following record types:

record R1(T1 P1);
record R2(T1 P1, T2 P2, T3 P3) : R1(P1);

Bu kayıt türleri için, birleştirilmiş yazdırma üyeleri şöyle bir şey olacaktır:For those record types, the synthesized printing members would be something like:

class R1 : IEquatable<R1>
{
    public T1 P1 { get; init; }
    
    protected virtual bool PrintMembers(StringBuilder builder)
    {
        builder.Append(nameof(P1));
        builder.Append(" = ");
        builder.Append(this.P1); // or builder.Append(this.P1.ToString()); if P1 has a value type
        
        return true;
    }
    
    public override string ToString()
    {
        var builder = new StringBuilder();
        builder.Append(nameof(R1));
        builder.Append(" { ");

        if (PrintMembers(builder))
            builder.Append(" ");

        builder.Append("}");
        return builder.ToString();
    }
}

class R2 : R1, IEquatable<R2>
{
    public T2 P2 { get; init; }
    public T3 P3 { get; init; }
    
    protected override bool PrintMembers(StringBuilder builder)
    {
        if (base.PrintMembers(builder))
            builder.Append(", ");
            
        builder.Append(nameof(P2));
        builder.Append(" = ");
        builder.Append(this.P2); // or builder.Append(this.P2); if P2 has a value type
        
        builder.Append(", ");
        
        builder.Append(nameof(P3));
        builder.Append(" = ");
        builder.Append(this.P3); // or builder.Append(this.P3); if P3 has a value type
        
        return true;
    }
    
    public override string ToString()
    {
        var builder = new StringBuilder();
        builder.Append(nameof(R2));
        builder.Append(" { ");

        if (PrintMembers(builder))
            builder.Append(" ");

        builder.Append("}");
        return builder.ToString();
    }
}

Konumsal kayıt üyeleriPositional record members

Yukarıdaki üyelere ek olarak, bir parametre listesi ("konumsal kayıtlar") içeren kayıtlar, yukarıdaki üyelerle aynı koşullara sahip ek üyeleri birleştirmeye benzer.In addition to the above members, records with a parameter list ("positional records") synthesize additional members with the same conditions as the members above.

Birincil OluşturucuPrimary Constructor

Bir kayıt türünün, imzası tür bildiriminin değer parametrelerine karşılık gelen bir ortak Oluşturucusu vardır.A record type has a public constructor whose signature corresponds to the value parameters of the type declaration. Bu, türü için birincil Oluşturucu olarak adlandırılır ve varsa örtülü olarak belirtilen varsayılan sınıf oluşturucusunun gizlenmesine neden olur.This is called the primary constructor for the type, and causes the implicitly declared default class constructor, if present, to be suppressed. Bir birincil oluşturucuya ve sınıfta zaten aynı imzaya sahip bir oluşturucuya sahip olmak bir hatadır.It is an error to have a primary constructor and a constructor with the same signature already present in the class.

Çalışma zamanında birincil OluşturucuAt runtime the primary constructor

  1. sınıf gövdesinde görünen örnek başlatıcıları yürütürexecutes the instance initializers appearing in the class-body

  2. varsa, yan tümce içinde belirtilen bağımsız değişkenlerle temel sınıf oluşturucusunu çağırır record_baseinvokes the base class constructor with the arguments provided in the record_base clause, if present

Bir kayıtta birincil Oluşturucu varsa, "kopya Oluşturucu" dışında herhangi bir Kullanıcı tanımlı oluşturucunun açık bir this Oluşturucu başlatıcısı olması gerekir.If a record has a primary constructor, any user-defined constructor, except "copy constructor" must have an explicit this constructor initializer.

Birincil oluşturucunun parametreleri ve kayıt üyeleri, argument_list record_base yan tümcesinin içindeki ve örnek alanları ya da özelliklerinin başlatıcıları içinde yer alan kapsamdadır.Parameters of the primary constructor as well as members of the record are in scope within the argument_list of the record_base clause and within initializers of instance fields or properties. Örnek üyeleri bu konumlarda bir hata olur (örneğin, örnek üyelerinin, bugün normal Oluşturucu başlatıcılarda kapsam içinde olduğu gibi), ancak birincil oluşturucunun parametreleri kapsamda ve kullanılabilir ve gölge Üyeler olabilir.Instance members would be an error in these locations (similar to how instance members are in scope in regular constructor initializers today, but an error to use), but the parameters of the primary constructor would be in scope and useable and would shadow members. Statik üyeler de, temel çağrıların ve başlatıcıların sıradan oluşturucularda hemen çalışmasına benzer şekilde de kullanılabilir.Static members would also be useable, similar to how base calls and initializers work in ordinary constructors today.

Birincil oluşturucunun parametresi okunmayan bir uyarı üretilir.A warning is produced if a parameter of the primary constructor is not read.

İçinde belirtilen ifade değişkenleri içindeki argument_list kapsamdadır argument_list .Expression variables declared in the argument_list are in scope within the argument_list. Normal bir Oluşturucu başlatıcısının bağımsız değişken listesi içindeki aynı gölgeleme kuralları geçerlidir.The same shadowing rules as within an argument list of a regular constructor initializer apply.

ÖzelliklerProperties

Bir kayıt türü bildiriminin her bir kayıt parametresi için, Name ve Type değeri Parameter bildiriminden alınan karşılık gelen bir ortak özellik üyesi vardır.For each record parameter of a record type declaration there is a corresponding public property member whose name and type are taken from the value parameter declaration.

Bir kayıt için:For a record:

  • Ortak get ve init otomatik özellik oluşturulur (bkz init . ayrı erişimci belirtimi).A public get and init auto-property is created (see separate init accessor specification). abstractEşleşen türe sahip devralınmış bir özellik geçersiz kılındı.An inherited abstract property with matching type is overridden. Devralınan özelliğin public geçersiz kılınabilir ve erişimciler yoksa, bu bir hatadır get init .It is an error if the inherited property does not have public overridable get and init accessors. Devralınan Özellik gizliyse bir hatadır.It is an error if the inherited property is hidden.
    Auto özelliği, karşılık gelen birincil Oluşturucu parametresinin değerine başlatılır.The auto-property is initialized to the value of the corresponding primary constructor parameter. Öznitelikler, property: field: ilişkili kayıt parametresine uygulanan sözdizimi için veya hedefleri kullanılarak, birleştirilmiş otomatik özelliğe ve bunun yedekleme alanına uygulanabilir.Attributes can be applied to the synthesized auto-property and its backing field by using property: or field: targets for attributes syntactically applied to the corresponding record parameter.

DeconstructDeconstruct

En az bir parametreye sahip konumsal bir kayıt, birincil Oluşturucu bildiriminin her parametresi için bir out parametresi bildirimiyle Deyapı adlı ortak bir void örnek yöntemi birleştirmektedir.A positional record with at least one parameter synthesizes a public void-returning instance method called Deconstruct with an out parameter declaration for each parameter of the primary constructor declaration. Deyapý yönteminin her parametresi, birincil Oluşturucu bildiriminin karşılık gelen parametresiyle aynı türde.Each parameter of the Deconstruct method has the same type as the corresponding parameter of the primary constructor declaration. Yönteminin gövdesi, Deyapý yönteminin her parametresini, aynı ada sahip bir üyeye erişen bir örnek üyesi olan değere atar.The body of the method assigns each parameter of the Deconstruct method to the value from an instance member access to a member of the same name. Yöntemi açıkça bildirilebilecek.The method can be declared explicitly. Açık bildirimin beklenen imza veya erişilebilirlikle eşleşmemesi veya statik olması hatadır.It is an error if the explicit declaration does not match the expected signature or accessibility, or is static.

with ifadesiniwith expression

Bir with ifade aşağıdaki sözdizimini kullanan yeni bir ifadedir.A with expression is a new expression using the following syntax.

with_expression
    : switch_expression
    | switch_expression 'with' '{' member_initializer_list? '}'
    ;

member_initializer_list
    : member_initializer (',' member_initializer)*
    ;

member_initializer
    : identifier '=' expression
    ;

Deyim with olarak bir ifadeye izin verilmez.A with expression is not permitted as a statement.

Bir with ifade, içindeki atamalarda bulunan değişikliklerle alıcı ifadesinin bir kopyasını oluşturmak için tasarlanan "bozucu olmayan mutation" için izin verir member_initializer_list .A with expression allows for "non-destructive mutation", designed to produce a copy of the receiver expression with modifications in assignments in the member_initializer_list.

Geçerli bir with ifade, void olmayan bir türe sahip bir alıcıya sahip.A valid with expression has a receiver with a non-void type. Alıcı türü bir kayıt olmalıdır.The receiver type must be a record.

İfadenin sağ tarafında with member_initializer_list , bir tanımlayıcıya atamalar dizisi vardır. Bu, erişilebilir bir örnek alanı veya alıcının türünün özelliği olmalıdır.On the right hand side of the with expression is a member_initializer_list with a sequence of assignments to identifier, which must be an accessible instance field or property of the receiver's type.

İlk olarak, alıcının "kopya" yöntemi (yukarıda belirtilen) çağrılır ve sonucu alıcının türüne dönüştürülür.First, receiver's "clone" method (specified above) is invoked and its result is converted to the receiver's type. Ardından, her biri member_initializer bir alan atama ile aynı şekilde işlenir ve dönüştürme sonucunun Özellik erişimi olur.Then, each member_initializer is processed the same way as an assignment to a field or property access of the result of the conversion. Atamalar, sözcük temelli sırada işlenir.Assignments are processed in lexical order.