C# 9.0 记录 - ToString 未继承
C# 9.0 records - ToString not inherited
考虑:
// the ratioale for Wrapper is that it has a Json serializer that
// serialize through Field (not included in this example)
record Wrapper<T> where T : notnull {
protected Wrapper(T field) => Field = field;
protected Wrapper(Wrapper<T> wrapper) => Field = wrapper.Field;
protected readonly T Field;
public override string ToString() => Field.ToString() ?? "";
}
record MyRec : Wrapper<string> {
public MyRec(string s) : base(s) {}
}
public static class Program {
public static void Main(string[] args) {
var r = new MyRec("hello");
Console.WriteLine(r.ToString());
}
}
似乎基 ToString
不是继承的,编译器仍然自动生成派生的 Tostring
这是为什么?有什么好的解决办法吗?
record
声明取代继承的 ToString()
。 What's New 描述中对此进行了解释:
The compiler synthesizes two methods that support printed output: a ToString() override, and PrintMembers.
基本 class(也是 record
)具有 ToString
覆盖的事实未被考虑。从技术上讲,所有 类型从 object
继承 ToString()
,因此 record
类型的代码生成器不会查看继承覆盖的基类型,否则compiler-generated ToString
将 永远不会 创建。
(您可能会争辩说应该保留继承的 record
类型中的 ToString
,但这不是该功能的设计方式)。
但是如果记录类型有一个被覆盖的 ToString()
,那么编译器不会生成一个:
If a record type has a method that matches the signature of any synthesized method, the compiler doesn't synthesize that method.
您可以定义一个看似多余的覆盖:
public override string ToString() => base.ToString();
由于 record
声明,这应该可以防止编译器 auto-generating ToString
覆盖。
有评论为我解决了这个问题。 Sean 说,如果您将 sealed 添加到方法中,它会阻止编译器合成 .ToString() 方法,请参见下文
public sealed override string ToString() => Value;
考虑:
// the ratioale for Wrapper is that it has a Json serializer that
// serialize through Field (not included in this example)
record Wrapper<T> where T : notnull {
protected Wrapper(T field) => Field = field;
protected Wrapper(Wrapper<T> wrapper) => Field = wrapper.Field;
protected readonly T Field;
public override string ToString() => Field.ToString() ?? "";
}
record MyRec : Wrapper<string> {
public MyRec(string s) : base(s) {}
}
public static class Program {
public static void Main(string[] args) {
var r = new MyRec("hello");
Console.WriteLine(r.ToString());
}
}
似乎基 ToString
不是继承的,编译器仍然自动生成派生的 Tostring
这是为什么?有什么好的解决办法吗?
record
声明取代继承的 ToString()
。 What's New 描述中对此进行了解释:
The compiler synthesizes two methods that support printed output: a ToString() override, and PrintMembers.
基本 class(也是 record
)具有 ToString
覆盖的事实未被考虑。从技术上讲,所有 类型从 object
继承 ToString()
,因此 record
类型的代码生成器不会查看继承覆盖的基类型,否则compiler-generated ToString
将 永远不会 创建。
(您可能会争辩说应该保留继承的 record
类型中的 ToString
,但这不是该功能的设计方式)。
但是如果记录类型有一个被覆盖的 ToString()
,那么编译器不会生成一个:
If a record type has a method that matches the signature of any synthesized method, the compiler doesn't synthesize that method.
您可以定义一个看似多余的覆盖:
public override string ToString() => base.ToString();
由于 record
声明,这应该可以防止编译器 auto-generating ToString
覆盖。
有评论为我解决了这个问题。 Sean 说,如果您将 sealed 添加到方法中,它会阻止编译器合成 .ToString() 方法,请参见下文
public sealed override string ToString() => Value;