【问题标题】:C# - Readonly properties and fields cannot be set in derived class constructors [duplicate]C# - 不能在派生类构造函数中设置只读属性和字段[重复]
【发布时间】:2019-12-13 04:25:08
【问题描述】:

我有一个类似下面的类结构

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

这会引发编译错误

不能将只读字段分配给(构造函数或变量初始化器除外)

无法将属性或索引器“AMyAbstractClass.MyReadonlyProperty”分配给 -- 它是只读的

分别。

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


我可以想出其他方法来获得不可变对象属性,但为什么不允许这种情况?这种封装有哪些好的做法?

【问题讨论】:

  • 第一个错误消息可能有点不清楚,但您只需要在基类中创建一个构造函数(也可能是protected)。
  • 这是我在 Visual Studio 2017 中收到的逐字错误消息。
  • 抽象类是否有构造函数在两种情况下都是一样的。

标签: c# constructor derived-class readonly-attribute


【解决方案1】:

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

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

关于readonly 字段。参考来自ECMA-334 C# Language Specification, chapter 15.5.3

当一个字段 - 声明包含一个只读修饰符,声明引入的字段为只读字段。直接分配给只读 字段只能作为该声明的一部分或在一个实例中出现 同一个类中的构造函数或静态构造函数。

以及来自 c# 6 的 read-only auto-properties 的描述:

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

【讨论】:

  • 我要补充一点(除非你正在使用 Unity),你应该真正避免公共变量(即使是只读的)。使用您的属性访问您的变量
  • 也请尝试回答我问题的“为什么”部分。
  • @Elaskanator,我已经引用了
  • 您的 ECMA 规范文章中的措辞是“...在同一个类别中”,确实如此。我仍然不明白为什么。关于自动属性的 MSDN 文章甚至没有指出限制。附言我不记得它叫什么了,感谢您挖掘“只读自动属性”链接。
  • @Elaskanator, 所以why in the same type's constructor only - 这对我来说很有意义,在我看来这是因为封装,这两种情况的只读性质意味着 outer 代码可能不要让他们改变,即使是子类型的构造函数也是一个外部代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-16
  • 1970-01-01
  • 2021-07-15
  • 2011-05-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多