为什么重写的 get-only 属性 在 base class 构造函数中设置时保持为空?
Why does an overridden get-only property stay null when set in base class constructor?
我尝试了以下示例:
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 保持为空。但为什么?
我真的不明白它的窍门,有人可以向我解释为什么会这样吗?至少我会期待一个错误,即只读 属性 不能设置在拥有 class.
之外
解释这一点的最简单方法是考虑编译器生成什么代码来实现它。
基数 class 等同于:
public class TestBase
{
public virtual string ReadOnly => _testBaseReadOnly;
public TestBase()
{
_testBaseReadOnly = "from base";
}
readonly string _testBaseReadOnly;
}
导出的class等同于:
class Test : TestBase
{
public override string ReadOnly => _testReadOnly;
readonly string _testReadOnly;
}
这里要注意的重要一点是,派生的 class 有自己的 ReadOnly
支持字段 - 它不会重复使用基础 class 中的那个。
意识到这一点后,重写的 属性 为空的原因就很明显了。
这是因为派生的 class 有自己的 ReadOnly
支持字段,并且其构造函数没有初始化该支持字段。
顺便说一下,如果你使用 Resharper
它实际上会警告你你没有在派生的 class:
中设置 ReadOnly
"Get-only auto-property 'ReadOnly' is never assigned."
编译器如下处理;基本上,构造函数中的代码写入 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
}
}
}
我尝试了以下示例:
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 保持为空。但为什么? 我真的不明白它的窍门,有人可以向我解释为什么会这样吗?至少我会期待一个错误,即只读 属性 不能设置在拥有 class.
之外解释这一点的最简单方法是考虑编译器生成什么代码来实现它。
基数 class 等同于:
public class TestBase
{
public virtual string ReadOnly => _testBaseReadOnly;
public TestBase()
{
_testBaseReadOnly = "from base";
}
readonly string _testBaseReadOnly;
}
导出的class等同于:
class Test : TestBase
{
public override string ReadOnly => _testReadOnly;
readonly string _testReadOnly;
}
这里要注意的重要一点是,派生的 class 有自己的 ReadOnly
支持字段 - 它不会重复使用基础 class 中的那个。
意识到这一点后,重写的 属性 为空的原因就很明显了。
这是因为派生的 class 有自己的 ReadOnly
支持字段,并且其构造函数没有初始化该支持字段。
顺便说一下,如果你使用 Resharper
它实际上会警告你你没有在派生的 class:
ReadOnly
"Get-only auto-property 'ReadOnly' is never assigned."
编译器如下处理;基本上,构造函数中的代码写入 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
}
}
}