为什么重写的get-only属性在基类构造函数中设置时保持为null



我尝试了以下示例:

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
}
}

当我创建Test的实例时,我看到ReadOnly保持为null。但为什么呢?我真的不明白,有人能解释一下为什么会发生这种事吗?至少我预计会出现一个错误,即不能在所属类之外设置只读属性。

编译器如下处理;基本上,构造函数中的代码写入TestBase中的原始备份字段。你的场景似乎不受支持,但是。。。我想知道语言团队是否考虑过这个案例。

BTW:如果你想看看编译器对代码做了什么: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
}
}
}

解释这一点的最简单方法是考虑编译器正在生成什么代码来实现它。

基类相当于:

public class TestBase
{
public virtual string ReadOnly => _testBaseReadOnly;
public TestBase()
{
_testBaseReadOnly = "from base";
}
readonly string _testBaseReadOnly;
}

派生类等效于:

class Test : TestBase
{
public override string ReadOnly => _testReadOnly;
readonly string _testReadOnly;
}

这里需要注意的重要一点是,派生类对ReadOnly有自己的BACKING字段——它不会重用基类中的那个字段。

意识到这一点后,应该很清楚为什么被重写的属性为null。

这是因为派生类有自己的ReadOnly支持字段,而它的构造函数没有初始化该支持字段。

顺便说一句,如果您使用Resharper,它实际上会警告您没有在派生类中设置ReadOnly

"Get-only auto-property 'ReadOnly' is never assigned."

相关内容

  • 没有找到相关文章

最新更新