記錄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_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
.
部分記錄的多個部分類型宣告可能會提供 parameter_list
。At 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
如果記錄類型為,則屬性為 sealed
。The property is private
if the record type is sealed
. 否則,屬性為 virtual
和 protected
。Otherwise, the property is virtual
and protected
.
可以明確宣告屬性。The property can be declared explicitly. 如果明確宣告不符合預期的簽章或存取範圍,或者明確的宣告不允許在衍生類型中覆寫,而且記錄類型不允許,則會產生錯誤 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
.
如果記錄類型是衍生自基底記錄類型 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. 如果明確宣告不符合預期的簽章或存取範圍,或者明確的宣告不允許在衍生類型中覆寫,而且記錄類型不允許,則會產生錯誤 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
. 如果綜合或明確宣告的屬性不會在記錄類型中使用此簽章覆寫屬性,則會產生錯誤 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
除非記錄類型為,否則方法為 sealed
。The method is public
, and the method is virtual
unless the record type is sealed
.
可以明確宣告方法。The method can be declared explicitly. 如果明確宣告不符合預期的簽章或存取範圍,或是明確的宣告不允許在衍生類型中覆寫,而且記錄類型不允許覆寫,則會是錯誤 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)
是使用者定義 (未合成) 但不 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
下列各項都有時,才會傳回合成 true
:The synthesized Equals(R?)
returns true
if and only if each of the following are true
:
other
不是null
,而是other
is notnull
, and- 針對
fieldN
不是繼承之記錄類型中的每個實例欄位,where 的System.Collections.Generic.EqualityComparer<TN>.Default.Equals(fieldN, other.fieldN)
值TN
是欄位類型,而For each instance fieldfieldN
in the record type that is not inherited, the value ofSystem.Collections.Generic.EqualityComparer<TN>.Default.Equals(fieldN, other.fieldN)
whereTN
is the field type, and - 如果有基底記錄類型,則 (的值為
base.Equals(other)
) 的非虛擬呼叫public virtual bool Equals(Base? other)
; 否則為的值EqualityContract == other.EqualityContract
。If there is a base record type, the value ofbase.Equals(other)
(a non-virtual call topublic virtual bool Equals(Base? other)
); otherwise the value ofEqualityContract == 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.
如果明確宣告不允許在衍生類型中覆寫,而且記錄類型不允許,則會產生錯誤 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
. 如果綜合或明確宣告的方法不會覆寫 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 fieldfieldN
in the record type that is not inherited, the value ofSystem.Collections.Generic.EqualityComparer<TN>.Default.GetHashCode(fieldN)
whereTN
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 ofbase.GetHashCode()
; otherwise the value ofSystem.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
如果記錄類型為,則方法為 sealed
。The method is private
if the record type is sealed
. 否則,方法為 virtual
和 protected
。Otherwise, the method is virtual
and protected
.
此方法:The method:
- 針對每一筆記錄的可列印成員 (非靜態公用欄位和可讀取的屬性成員) ,會附加該成員的名稱,後面接著 "=",後面接著以 "," 分隔的成員值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 ", ",
- 如果記錄具有可列印的成員,則傳回 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.Append
。At 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:
PrintMembers
使用一個引數來呼叫基底方法builder
, (其參數) ,calls the basePrintMembers
method with one argument (itsbuilder
parameter),- 如果
PrintMembers
方法傳回 true,請將 "," 附加至 builderif thePrintMembers
method returned true, append ", " to the builder, - 針對每個記錄的可列印成員,附加該成員的名稱,後面接著 "=",後面接著成員的值:
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
(orthis.member.ToString()
for value types), separated with ", ", - 傳回 true。return true.
PrintMembers
可以明確宣告方法。The PrintMembers
method can be declared explicitly.
如果明確宣告不符合預期的簽章或存取範圍,或者明確的宣告不允許在衍生類型中覆寫,而且記錄類型不允許,則會產生錯誤 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
.
記錄包含的合成方法相當於宣告如下的方法:The record includes a synthesized method equivalent to a method declared as follows:
public override string ToString();
可以明確宣告方法。The method can be declared explicitly. 如果明確宣告不符合預期的簽章或存取範圍,或者明確的宣告不允許在衍生類型中覆寫,而且記錄類型不允許,則會產生錯誤 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
. 如果綜合或明確宣告的方法不會覆寫 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:
- 建立
StringBuilder
實例,creates aStringBuilder
instance, - 將記錄名稱附加至 builder,後面接著 "{"、appends the record name to the builder, followed by " { ",
- 叫用記錄的
PrintMembers
方法,將它提供給產生器,後面接著 "" (如果傳回 true)。invokes the record'sPrintMembers
method giving it the builder, followed by " " if it returned true, - 附加 "}"、appends "}",
- 傳回產生器的內容
builder.ToString()
。returns the builder's contents withbuilder.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
執行出現在類別主體中的實例初始化運算式executes the instance initializers appearing in the class-body
使用子句中提供的引數來叫用基類的函式
record_base
(如果有的話)invokes the base class constructor with the arguments provided in therecord_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_list
。Expression 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:
- 建立公用
get
和init
自動屬性 (請參閱個別init
的存取子規格) 。A publicget
andinit
auto-property is created (see separateinit
accessor specification). 覆abstract
寫了具有相符類型的繼承屬性。An inheritedabstract
property with matching type is overridden. 如果繼承的屬性沒有可覆public
寫和存取子,就會產生錯誤get
init
。It is an error if the inherited property does not havepublic
overridableget
andinit
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 usingproperty:
orfield:
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_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
.
有效的 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.