記錄Records

本提案會追蹤 c # 9 記錄功能的規格,如同 c # 語言設計小組所同意。This proposal tracks the specification for the C# 9 records feature, as agreed to by the C# language design team.

記錄的語法如下所示: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* '}' ';'?
    | ';'
    ;

記錄類型是參考型別,類似于類別宣告。Record types are reference types, similar to a class declaration. 如果未包含,則記錄提供的錯誤為 record_base argument_list record_declaration parameter_listIt is an error for a record to provide a record_base argument_list if the record_declaration does not contain a parameter_list. 部分記錄的多個部分類型宣告可能會提供 parameter_listAt most one partial type declaration of a partial record may provide a parameter_list.

記錄參數無法使用 ref 或修飾詞 out this (但 in params 允許) 。Record parameters cannot use ref, out or this modifiers (but in and params are allowed).

繼承Inheritance

記錄無法繼承自類別,除非類別為 object ,而且類別無法繼承自記錄。Records cannot inherit from classes, unless the class is object, and classes cannot inherit from records. 記錄可以繼承自其他記錄。Records can inherit from other records.

記錄類型的成員Members of a record type

除了記錄主體中宣告的成員之外,記錄類型還有其他合成成員。In addition to the members declared in the record body, a record type has additional synthesized members. 成員是合成的,除非在記錄主體中宣告具有「相符」簽章的成員,或繼承具有「比對」簽章的可存取的具象非虛擬成員。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. 如果兩個成員具有相同的簽章,或在繼承案例中被視為「隱藏」,則會將它們視為相符。Two members are considered matching if they have the same signature or would be considered "hiding" in an inheritance scenario. 將記錄的成員命名為 "Clone" 時,會發生錯誤。It is an error for a member of a record to be named "Clone". 記錄的實例欄位具有不安全的型別時,會發生錯誤。It is an error for an instance field of a record to have an unsafe type.

合成成員如下所示:The synthesized members are as follows:

等號成員Equality members

如果是衍生自的記錄 object ,記錄類型會包含與宣告的屬性相等的合成 readonly 屬性,如下所示: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; };

private如果記錄類型為,則屬性為 sealedThe property is private if the record type is sealed. 否則,屬性為 virtualprotectedOtherwise, the property is virtual and protected. 可以明確宣告屬性。The property can be declared explicitly. 如果明確宣告不符合預期的簽章或存取範圍,或者明確的宣告不允許在衍生類型中覆寫,而且記錄類型不允許,則會產生錯誤 sealedIt 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.

如果記錄類型是衍生自基底記錄類型 Base ,則記錄類型會包含與宣告的屬性相等的合成 readonly 屬性,如下所示: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; };

可以明確宣告屬性。The property can be declared explicitly. 如果明確宣告不符合預期的簽章或存取範圍,或者明確的宣告不允許在衍生類型中覆寫,而且記錄類型不允許,則會產生錯誤 sealedIt 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. 如果綜合或明確宣告的屬性不會在記錄類型中使用此簽章覆寫屬性,則會產生錯誤 Base (例如,如果屬性在中遺失,或已 Base 密封或非虛擬等 ) 。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.). 合成的屬性會傳回, typeof(R) 其中 R 是記錄類型。The synthesized property returns typeof(R) where R is the record type.

記錄類型 System.IEquatable<R> 會執行,並包含合成的強型別多載, 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. 方法為 public ,而且 virtual 除非記錄類型為,否則方法為 sealedThe method is public, and the method is virtual unless the record type is sealed. 可以明確宣告方法。The method can be declared explicitly. 如果明確宣告不符合預期的簽章或存取範圍,或是明確的宣告不允許在衍生類型中覆寫,而且記錄類型不允許覆寫,則會是錯誤 sealedIt 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) 是使用者定義 (未合成) 但不 GetHashCode 是,則會產生警告。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 下列各項都有時,才會傳回合成 trueThe synthesized Equals(R?) returns true if and only if each of the following are true:

  • other 不是 null ,而是other is not null, and
  • 針對 fieldN 不是繼承之記錄類型中的每個實例欄位,where 的 System.Collections.Generic.EqualityComparer<TN>.Default.Equals(fieldN, other.fieldN)TN 是欄位類型,而For 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
  • 如果有基底記錄類型,則 (的值為 base.Equals(other)) 的非虛擬呼叫 public virtual bool Equals(Base? other) ; 否則為的值 EqualityContract == other.EqualityContractIf 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.

記錄類型包括合成 ==!= 運算子,相當於宣告如下的運算子: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運算子呼叫的方法 ==Equals(R? other) 上述指定的方法。The Equals method called by the == operator is the Equals(R? other) method specified above. !=運算子會委派給 == 運算子。The != operator delegates to the == operator. 如果已明確宣告運算子,就會發生錯誤。It is an error if the operators are declared explicitly.

如果記錄類型是衍生自基底記錄類型 Base ,記錄類型會包含與宣告的方法相等的合成覆寫,如下所示: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);

如果覆寫明確宣告,就會發生錯誤。It is an error if the override is declared explicitly. 如果方法未在記錄類型中覆寫具有相同簽章的方法,就會發生錯誤 Base (例如,如果方法在 Base 、密封或非虛擬等 ) 中遺失。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.). 合成覆寫會傳回 Equals((object?)other)The synthesized override returns Equals((object?)other).

記錄類型包含與宣告的方法相等的合成覆寫,如下所示:The record type includes a synthesized override equivalent to a method declared as follows:

public override bool Equals(object? obj);

如果覆寫明確宣告,就會發生錯誤。It is an error if the override is declared explicitly. 如果方法未覆寫 object.Equals(object? obj) ((例如,因為中繼基底類型中有遮蔽 ) 等),就會發生錯誤。It is an error if the method doesn't override object.Equals(object? obj) (for example, due to shadowing in intermediate base types, etc.). 合成覆寫會傳回, Equals(other as R) 其中 R 是記錄類型。The synthesized override returns Equals(other as R) where R is the record type.

記錄類型包含與宣告的方法相等的合成覆寫,如下所示:The record type includes a synthesized override equivalent to a method declared as follows:

public override int GetHashCode();

可以明確宣告方法。The method can be declared explicitly. 如果明確宣告不允許在衍生類型中覆寫,而且記錄類型不允許,則會產生錯誤 sealedIt is an error if the explicit declaration doesn't allow overriding it in a derived type and the record type is not sealed. 如果綜合或明確宣告的方法不會覆寫 object.GetHashCode() (例如,因為中繼基底型別中的遮蔽等 ) ,就會發生錯誤。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.).

如果已明確宣告其中一個 Equals(R?) 和, GetHashCode() 但另一個方法並非明確宣告,則會回報警告。A warning is reported if one of Equals(R?) and GetHashCode() is explicitly declared but the other method is not explicit.

的合成覆寫會傳回 GetHashCode() int 合併下列值的結果:The synthesized override of GetHashCode() returns an int result of combining the following values:

  • 針對 fieldN 不是繼承之記錄類型中的每個實例欄位,where 的 System.Collections.Generic.EqualityComparer<TN>.Default.GetHashCode(fieldN)TN 是欄位類型,而For 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
  • 如果有基底記錄類型,則為的值,否則為的 base.GetHashCode()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).

例如,請考慮下列記錄類型: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);

針對這些記錄類型,合成等號成員會是類似如下的內容: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));
    }
}

複製和複製成員Copy and Clone members

記錄類型包含兩個複製成員:A record type contains two copying members:

  • 採用記錄類型之單一引數的函式。A constructor taking a single argument of the record type. 這稱為「複製函式」。It is referred to as a "copy constructor".
  • 使用編譯器保留名稱的合成公用無參數實例「複製」方法A synthesized public parameterless instance "clone" method with a compiler-reserved name

複製函式的目的是要將狀態從參數複製到所建立的新實例。The purpose of the copy constructor is to copy the state from the parameter to the new instance being created. 這個函式不會執行記錄宣告中出現的任何實例欄位/屬性初始化運算式。This constructor doesn't run any instance field/property initializers present in the record declaration. 如果未明確宣告函式,則編譯器會合成函式。If the constructor is not explicitly declared, a constructor will be synthesized by the compiler. 如果記錄是密封的,則此函式會是私用的,否則會受到保護。If the record is sealed, the constructor will be private, otherwise it will be protected. 明確宣告的複製函式必須是公用或受保護的,除非該記錄已密封。An explicitly declared copy constructor must be either public or protected, unless the record is sealed. 此函式必須做的第一件事,是呼叫基底的複製函式,或如果記錄繼承自 object,則為無參數物件的函式。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. 如果使用者定義的複製函式使用不符合這項需求的隱含或明確的函式初始化運算式,就會回報錯誤。An error is reported if a user-defined copy constructor uses an implicit or explicit constructor initializer that doesn't fulfill this requirement. 在叫用基底複製函式之後,合成複製的函式會針對記錄類型內隱含或明確宣告的所有實例欄位,複製值。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. 複製函式的唯一存在(不論是明確或隱含),都不會導致自動新增預設實例的函式。The sole presence of a copy constructor, whether explicit or implicit, doesn't prevent an automatic addition of a default instance constructor.

如果基底記錄中有虛擬的「複製」方法,合成的「複製」方法會覆寫它,而如果支援「協變數傳回」功能和覆寫傳回型別,則方法的傳回型別會是目前的包含型別。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. 如果基底記錄複製方法是密封的,則會產生錯誤。An error is produced if the base record clone method is sealed. 如果基底記錄中沒有虛擬的「複製」方法,則複製方法的傳回型別會是包含型別,而此方法是虛擬的,除非該記錄是密封或抽象的。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. 如果包含的記錄是抽象的,則合成複製方法也是抽象的。If the containing record is abstract, the synthesized clone method is also abstract. 如果「複製」方法不是抽象的,則會傳回對複製函式之呼叫的結果。If the "clone" method is not abstract, it returns the result of a call to a copy constructor.

列印成員: PrintMembers 和 ToString 方法Printing members: PrintMembers and ToString methods

如果是衍生自的記錄 object ,記錄就會包含與宣告如下的方法相等的合成方法: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);

private如果記錄類型為,則方法為 sealedThe method is private if the record type is sealed. 否則,方法為 virtualprotectedOtherwise, the method is virtual and protected.

此方法:The method:

  1. 針對每一筆記錄的可列印成員 (非靜態公用欄位和可讀取的屬性成員) ,會附加該成員的名稱,後面接著 "=",後面接著以 "," 分隔的成員值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. 如果記錄具有可列印的成員,則傳回 true。return true if the record has printable members.

對於具有實數值型別的成員,我們會使用目標平臺可用的最有效率方法,將它的值轉換為字串表示。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. 目前,這表示在 ToString 傳遞至之前呼叫 StringBuilder.AppendAt present that means calling ToString before passing to StringBuilder.Append.

如果記錄類型衍生自基底記錄 Base ,此記錄會包含與宣告的方法相等的合成覆寫,如下所示: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);

如果記錄沒有可列印的成員,方法會呼叫基底 PrintMembers 方法,其中一個引數 (其 builder 參數) 並傳回結果。If the record has no printable members, the method calls the base PrintMembers method with one argument (its builder parameter) and returns the result.

否則,方法會:Otherwise, the method:

  1. PrintMembers使用一個引數來呼叫基底方法 builder , (其參數) ,calls the base PrintMembers method with one argument (its builder parameter),
  2. 如果 PrintMembers 方法傳回 true,請將 "," 附加至 builderif the PrintMembers method returned true, append ", " to the builder,
  3. 針對每個記錄的可列印成員,附加該成員的名稱,後面接著 "=",後面接著成員的值: this.member (或實 this.member.ToString() 數值型別) ,以 "," 分隔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。return true.

PrintMembers可以明確宣告方法。The PrintMembers method can be declared explicitly. 如果明確宣告不符合預期的簽章或存取範圍,或者明確的宣告不允許在衍生類型中覆寫,而且記錄類型不允許,則會產生錯誤 sealedIt 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.

記錄包含的合成方法相當於宣告如下的方法:The record includes a synthesized method equivalent to a method declared as follows:

public override string ToString();

可以明確宣告方法。The method can be declared explicitly. 如果明確宣告不符合預期的簽章或存取範圍,或者明確的宣告不允許在衍生類型中覆寫,而且記錄類型不允許,則會產生錯誤 sealedIt 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. 如果綜合或明確宣告的方法不會覆寫 object.ToString() (例如,因為中繼基底型別中的遮蔽等 ) ,就會發生錯誤。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.).

合成的方法:The synthesized method:

  1. 建立 StringBuilder 實例,creates a StringBuilder instance,
  2. 將記錄名稱附加至 builder,後面接著 "{"、appends the record name to the builder, followed by " { ",
  3. 叫用記錄的 PrintMembers 方法,將它提供給產生器,後面接著 "" (如果傳回 true)。invokes the record's PrintMembers method giving it the builder, followed by " " if it returned true,
  4. 附加 "}"、appends "}",
  5. 傳回產生器的內容 builder.ToString()returns the builder's contents with builder.ToString().

例如,請考慮下列記錄類型:For example, consider the following record types:

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

針對這些記錄類型,合成的列印成員會是類似如下的內容: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();
    }
}

位置記錄成員Positional record members

除了上述成員之外,以參數清單 ( 「位置記錄」的記錄 ) 合成其他成員與上述成員具有相同條件的成員。In addition to the above members, records with a parameter list ("positional records") synthesize additional members with the same conditions as the members above.

主要的函式Primary Constructor

記錄類型有一個公用的函式,其簽章對應至類型宣告的值參數。A record type has a public constructor whose signature corresponds to the value parameters of the type declaration. 這稱為型別的主要函式,並會導致隱含宣告的預設類別(如果有的話)。This is called the primary constructor for the type, and causes the implicitly declared default class constructor, if present, to be suppressed. 具有相同簽章的主要函式和函式已存在於類別中,是錯誤的。It is an error to have a primary constructor and a constructor with the same signature already present in the class.

在執行時間,主要的函式At runtime the primary constructor

  1. 執行出現在類別主體中的實例初始化運算式executes the instance initializers appearing in the class-body

  2. 使用子句中提供的引數來叫用基類的函式 record_base (如果有的話)invokes the base class constructor with the arguments provided in the record_base clause, if present

如果記錄有主要的函式,則任何使用者定義的函式(「複製函式」除外)都必須有明確的函式 this 初始化運算式。If a record has a primary constructor, any user-defined constructor, except "copy constructor" must have an explicit this constructor initializer.

主要函式以及記錄成員的參數,位於子句內的範圍內 argument_list record_base ,以及實例欄位或屬性的初始化運算式內。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. 實例成員在這些位置中會是錯誤 (類似于現今的一般函式初始化運算式的範圍中實例成員的範圍,但使用) 的錯誤,但主要函式的參數在範圍內且可使用,而且會遮蔽成員。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. 靜態成員也可以使用,類似于目前在一般的函式中,基底呼叫和初始化運算式的運作方式。Static members would also be useable, similar to how base calls and initializers work in ordinary constructors today.

如果未讀取主要函式的參數,則會產生警告。A warning is produced if a parameter of the primary constructor is not read.

中宣告的運算式變數位於 argument_list 的範圍內 argument_listExpression variables declared in the argument_list are in scope within the argument_list. 適用于一般的函式初始化運算式之引數清單中的相同遮蔽規則。The same shadowing rules as within an argument list of a regular constructor initializer apply.

屬性Properties

針對記錄類型宣告的每個記錄參數,有一個對應的公用屬性成員,其名稱和類型取自值參數宣告。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.

針對記錄:For a record:

  • 建立公用 getinit 自動屬性 (請參閱個別 init 的存取子規格) 。A public get and init auto-property is created (see separate init accessor specification). abstract 寫了具有相符類型的繼承屬性。An inherited abstract property with matching type is overridden. 如果繼承的屬性沒有可覆 public 寫和存取子,就會產生錯誤 get initIt is an error if the inherited property does not have public overridable get and init accessors. 如果已隱藏繼承的屬性,就會發生錯誤。It is an error if the inherited property is hidden.
    Auto 屬性會初始化為對應主要函式參數的值。The auto-property is initialized to the value of the corresponding primary constructor parameter. 您可以使用或將屬性 property: field: 的目標套用至對應的記錄參數,以將屬性套用至合成 auto 屬性及其支援欄位。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.

解 構Deconstruct

具有至少一個參數的位置記錄會會合成公用的 void 傳回實例方法(稱為解構),並針對主要的函式宣告的每個參數使用 out 參數宣告。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. 解構方法的每個參數都具有與主要函式宣告的對應參數相同的類型。Each parameter of the Deconstruct method has the same type as the corresponding parameter of the primary constructor declaration. 方法的主體會將解構方法的每個參數指派給實例成員的值,以存取相同名稱的成員。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. 可以明確宣告方法。The method can be declared explicitly. 如果明確宣告不符合預期的簽章或存取範圍,或者是靜態的,則會是錯誤。It is an error if the explicit declaration does not match the expected signature or accessibility, or is static.

with 運算式with expression

with運算式是使用下列語法的新運算式。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
    ;

with不允許使用運算式作為語句。A with expression is not permitted as a statement.

with運算式允許「非破壞性的變化」,其設計目的是要產生接收者運算式的複本,並修改中的指派 member_initializer_listA 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.

有效的 with 運算式具有非 void 類型的接收者。A valid with expression has a receiver with a non-void type. 接收者類型必須是記錄。The receiver type must be a record.

with運算式右側是 member_initializer_list 具有一系列指派給 識別碼 的,其必須是可存取的實例欄位或接收器型別的屬性。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.

首先,會叫用接收器的「clone」方法 (上面指定的) ,並將其結果轉換成接收者的型別。First, receiver's "clone" method (specified above) is invoked and its result is converted to the receiver's type. 然後,每個 member_initializer 處理的處理方式與指派給轉換結果之欄位或屬性存取的方式相同。Then, each member_initializer is processed the same way as an assignment to a field or property access of the result of the conversion. 指派會以詞法連續處理。Assignments are processed in lexical order.