记录有共同的基数 class 吗?
Is there a common base class for records?
我认为在 .NET 类型系统中,所有引用类型都派生自 System.Object
,所有值类型都派生自 System.ValueType
。是否还有一个公共基础 class 所有 record
类型都派生自?如果不是,为什么不呢?
Is there also a common base class all record types are derived from?
不,至少不是特定于记录的任何内容。记录只是引用类型。它们可以直接从 System.Object
或其他记录类型派生。
If not, why not?
它们不需要像值类型那样由运行时进行特殊处理。它们的所有特别之处都在编译器为它们生成的代码中。
“根”记录
记录可以直接从 System.Object
派生,无论是隐式还是显式,就像任何 class
一样。第一级记录类型引导记录的内部结构,建立记录类型层次结构的根。
复制构造函数 -- 受保护的构造函数,它接受对同一类型的引用并复制其属性。派生记录将从它们的复制构造函数中调用它。
克隆方法 -- 如果它曾经是Base Class 库的一部分,但是这个有一个无法寻址的名称:<Clone>$
。当您使用 with
关键字时,它会调用 <Clone>$
,它使用复制构造函数创建一个新实例,然后编译器允许在初始化表达式中设置任何仅用于初始化的属性。
平等成员 -- 这是一个大问题,因为记录是关于值语义的。来自 System.Object
的 GetHashCode
和 Equals
方法被覆盖,并且 IEquatable<T>.Equals()
被实现。还有一个protected 属性 named EqualityContract
用于相等比较,通过只比较公共部分来确保不同类型的记录不被认为是相等的。 ==
和 !=
运算符也被重载。
ToString
方法 -- 重载以显示记录的成员。它使用受保护的 PrintMembers
方法,调用 class 层次结构以构建包含所有属性值的字符串。
Deconstruct
方法 -- 使记录能够解构为单独的变量。
派生记录
当您为记录类型指定基本类型(System.Object
除外)时,它必须是另一种记录类型,因为它需要由记录类型层次结构的根建立的机制。派生记录类型定义相同的成员,但标记为 virtual
的成员现在标记为 override
.
复制构造函数 -- 这将调用基本记录的复制构造函数。
Clone 方法 -- <Clone>$
被覆盖为 return 使用其复制构造函数的更多派生类型。
Fun fact: This does not use the new covariant returns feature to declare a more derived return type on the overridden method, even though it returns a more derived type. That's because 1) it doesn't need to, and 2) it would've made records unusable except in .NET 5.0 since support for the feature was added in the .NET 5.0 runtime.
相等成员 -- 覆盖了相同的方法并定义了运算符,但考虑了任何新属性以实现相等。
ToString
方法 -- ToString
和 PrintMembers
被覆盖。 ToString
在字符串中生成实际的 class 名称和花括号。不调用基本实现。 PrintMembers
单独构建 属性 名称和值。
Deconstruct
method -- 这里没有重写,因为基础class的方法没有被标记virtual
.如果引入了新属性,则签名与基础 class 的签名不同,因此无需覆盖任何内容。如果没有引入新的属性,则该方法被标记为 new
以隐藏基础 class.
中的方法
这就是为什么不需要特殊的记录基类型的原因。
特别说明:
当记录被标记为 sealed
时,通常为 protected virtual
(但不是 protected override
)的成员变为 private
。这有多广泛取决于它是来自 System.Object
还是其他记录类型。
上面的 None 通过提供您自己的通常由编译器实现的任何方法的实现来考虑自定义。
我认为在 .NET 类型系统中,所有引用类型都派生自 System.Object
,所有值类型都派生自 System.ValueType
。是否还有一个公共基础 class 所有 record
类型都派生自?如果不是,为什么不呢?
Is there also a common base class all record types are derived from?
不,至少不是特定于记录的任何内容。记录只是引用类型。它们可以直接从 System.Object
或其他记录类型派生。
If not, why not?
它们不需要像值类型那样由运行时进行特殊处理。它们的所有特别之处都在编译器为它们生成的代码中。
“根”记录
记录可以直接从 System.Object
派生,无论是隐式还是显式,就像任何 class
一样。第一级记录类型引导记录的内部结构,建立记录类型层次结构的根。
复制构造函数 -- 受保护的构造函数,它接受对同一类型的引用并复制其属性。派生记录将从它们的复制构造函数中调用它。
克隆方法 -- 如果它曾经是Base Class 库的一部分,但是这个有一个无法寻址的名称:
<Clone>$
。当您使用with
关键字时,它会调用<Clone>$
,它使用复制构造函数创建一个新实例,然后编译器允许在初始化表达式中设置任何仅用于初始化的属性。平等成员 -- 这是一个大问题,因为记录是关于值语义的。来自
System.Object
的GetHashCode
和Equals
方法被覆盖,并且IEquatable<T>.Equals()
被实现。还有一个protected 属性 namedEqualityContract
用于相等比较,通过只比较公共部分来确保不同类型的记录不被认为是相等的。==
和!=
运算符也被重载。ToString
方法 -- 重载以显示记录的成员。它使用受保护的PrintMembers
方法,调用 class 层次结构以构建包含所有属性值的字符串。Deconstruct
方法 -- 使记录能够解构为单独的变量。
派生记录
当您为记录类型指定基本类型(System.Object
除外)时,它必须是另一种记录类型,因为它需要由记录类型层次结构的根建立的机制。派生记录类型定义相同的成员,但标记为 virtual
的成员现在标记为 override
.
复制构造函数 -- 这将调用基本记录的复制构造函数。
Clone 方法 --
<Clone>$
被覆盖为 return 使用其复制构造函数的更多派生类型。
Fun fact: This does not use the new covariant returns feature to declare a more derived return type on the overridden method, even though it returns a more derived type. That's because 1) it doesn't need to, and 2) it would've made records unusable except in .NET 5.0 since support for the feature was added in the .NET 5.0 runtime.
相等成员 -- 覆盖了相同的方法并定义了运算符,但考虑了任何新属性以实现相等。
ToString
方法 --ToString
和PrintMembers
被覆盖。ToString
在字符串中生成实际的 class 名称和花括号。不调用基本实现。PrintMembers
单独构建 属性 名称和值。
中的方法Deconstruct
method -- 这里没有重写,因为基础class的方法没有被标记virtual
.如果引入了新属性,则签名与基础 class 的签名不同,因此无需覆盖任何内容。如果没有引入新的属性,则该方法被标记为new
以隐藏基础 class.
这就是为什么不需要特殊的记录基类型的原因。
特别说明:
当记录被标记为 sealed
时,通常为 protected virtual
(但不是 protected override
)的成员变为 private
。这有多广泛取决于它是来自 System.Object
还是其他记录类型。
None 通过提供您自己的通常由编译器实现的任何方法的实现来考虑自定义。