为什么在具有主构造函数的记录中需要显式的“this”构造函数初始值设定项?
c#
c#-9.0
在 C# 9 中,我们可以创建位置记录,使它们获得一个构造函数,规范草案将其称为主构造函数。我们也可以创建自定义构造函数,但如规范中所述:
如果记录具有主构造函数,则任何用户定义的构造函数(“复制构造函数”除外)都必须具有显式的 this 构造函数初始值设定项。
所以这是不允许的:
public record A(string Foo, int Bar)
{
public A(MyClass x)
{
Foo = x.Name;
Bar = x.Number;
}
}
并且确实导致 CS8862“在带有参数列表的记录中声明的构造函数必须具有 'this' 构造函数初始值设定项。” 我们必须写:
public record A(string Foo, int Bar)
{
public A(MyClass x) : this(x.Name, x.Number) {}
}
反而。在这种情况下,这几乎不是问题,但可以想象一个更长的初始化逻辑,它不适合this构造函数初始化程序。
问题是:为什么存在这种限制?我猜想解除它会以某种方式打破记录的某些功能,但这是一个足够新的功能,我无法想出办法来做到这一点。自动生成的主构造函数是否做了一些对记录正常工作至关重要的事情,因此必须调用它?
回答
这是因为主构造函数参数有点特殊——它们在整个记录的初始化过程中都在范围内。猜猜下面的程序打印什么:
System.Console.WriteLine(new Foo(Bar: 42).Baz);
public record Foo(int Bar) {
public int Bar => 41;
public int Baz = Bar;
}
41或者42?
而答案是……
鼓声请...
42!
这里发生了什么?
在记录的初始化过程中,任何对Bar属性的引用都不是引用属性Bar,而是引用主构造函数参数Bar。
这意味着必须调用主构造函数。否则在这种情况下会发生什么:
System.Console.WriteLine(new Foo().Baz);
public record Foo(int Bar) {
public Foo(){}
public int Bar => 41;
public int Baz = Bar; // What is Bar here when the primary constructor isn't called.
}
在旁边
该Bar参数仅在初始化期间有效。初始化后,该Bar属性在范围内。如果我们稍微改变一下我们的例子:
System.Console.WriteLine(new Foo(Bar: 42).Baz);
public record Foo(int Bar) {
public int Bar => 41;
public int Baz => Bar; //Note this is `=>` not `=`
}
它会打印41.
THE END
二维码