C#-无法在派生类构造函数中设置只读属性和字段

Ela*_*tor 4 c# constructor derived-class readonly-attribute

我有一个像下面这样的类结构

abstract class AMyAbstractClass {
    public readonly int MyReadonlyField;
    public int MyReadonlyProperty { get; }//read-only auto-property (syntactic sugar)
}
class MyConcreteClass : AMyAbstractClass {
    MyConcreteClass() {
        this.MyReadonlyField = 1;
        this.MyReadonlyProperty = 1;
    }
}
Run Code Online (Sandbox Code Playgroud)

抛出编译错误

无法将只读字段分配给它(在构造函数或变量初始化程序中除外)

无法将属性或索引器'AMyAbstractClass.MyReadonlyProperty分配给它-只读

分别。

在第一种情况下,错误消息是错误的,因为它在构造函数中设置的!


我可以想出具有不可变对象属性的替代方法,但是为什么不允许这种情况呢?这种封装有哪些好的做法?

Ren*_*nat 6

您需要通过基类的构造函数传播它们:

abstract class AMyAbstractClass {
    public readonly int MyReadonlyField;
    public int MyReadonlyProperty { get; }//syntactic sugar
    protected AMyAbstractClass (int fieldValue, int propertyValue) {
        this.MyReadonlyField = fieldValue;
        this.MyReadonlyProperty = propertyValue;
    }
}
class MyConcreteClass : AMyAbstractClass {
    public MyConcreteClass() 
        : base(fieldValue: 1, propertyValue:1) {
    }
}
Run Code Online (Sandbox Code Playgroud)

关于readonly领域。参考ECMA-334 C#语言规范的第15.5.3章

当字段声明包含只读修饰符时,该声明引入的字段就是只读字段。对只读字段的直接分配只能在该声明的一部分或在同一类的实例构造函数或静态构造函数中发生。

以及来自c#6的只读自动属性的描述:

...属性只能在构造函数的主体中设置:

  • 我想补充一点(除非你正在做Unity)你应该真正避免公共变量(即使是只读的)。使用您的属性来访问您的变量 (2认同)
  • @Elaskanator,所以“为什么只在同一类型的构造函数中使用”-对我来说很有意义,我认为这是由于封装的原因,这两种情况的只读性质意味着**外部**代码可能不会改变它们,即使是子类型的构造函数也是这里的外部代码 (2认同)