apf*_*l24 45 c# automatic-properties
我尝试了以下示例:
public class TestBase
{
public virtual string ReadOnly { get; }
public TestBase()
{
ReadOnly = "from base";
}
}
class Test : TestBase
{
public override string ReadOnly { get; }
public Test()
{
// nothing here
}
}
Run Code Online (Sandbox Code Playgroud)
当我创建一个Test实例时,我看到ReadOnly保持为null.但为什么?我真的不明白它,有人可以向我解释为什么会这样吗?至少我会期望和错误,只能在拥有类之外设置只读属性.
Mar*_*ell 39
编译器将其视为如下; 基本上,构造函数中的代码写入原始支持字段TestBase.看来你的不支持场景,但是......我确实想知道语言团队是否考虑过这种情况.
顺便说一句:如果你想看看编译器对代码的作用:sharplab.io
public class TestBase
{
[CompilerGenerated]
private readonly string <ReadOnly>k__BackingField; // note: not legal in "real" C#
public virtual string ReadOnly
{
[CompilerGenerated]
get
{
return <ReadOnly>k__BackingField; // the one in TestBase
}
}
public TestBase()
{
<ReadOnly>k__BackingField = "from base";
}
}
internal class Test : TestBase
{
[CompilerGenerated]
private readonly string <ReadOnly>k__BackingField;
public override string ReadOnly
{
[CompilerGenerated]
get
{
return <ReadOnly>k__BackingField; // the one in Test
}
}
}
Run Code Online (Sandbox Code Playgroud)
Mat*_*son 17
解释这个的最简单方法是考虑编译器生成什么代码来实现它.
基类等同于:
public class TestBase
{
public virtual string ReadOnly => _testBaseReadOnly;
public TestBase()
{
_testBaseReadOnly = "from base";
}
readonly string _testBaseReadOnly;
}
Run Code Online (Sandbox Code Playgroud)
派生类等同于:
class Test : TestBase
{
public override string ReadOnly => _testReadOnly;
readonly string _testReadOnly;
}
Run Code Online (Sandbox Code Playgroud)
这里要注意的重要一点是派生类有它的OWN BACKING FIELD ReadOnly- 它不会重用基类中的那个.
意识到这一点后,显然为什么被覆盖的属性为null.
这是因为派生类有自己的支持字段ReadOnly,并且其构造函数不初始化该支持字段.
顺便说一句,如果你正在使用Resharper它,它实际上会警告你,你没有ReadOnly在派生类中进行设置:
"Get-only auto-property 'ReadOnly' is never assigned."
Run Code Online (Sandbox Code Playgroud)