【问题标题】:readonly-fields as targets from subclass constructors只读字段作为子类构造函数的目标
【发布时间】:2011-12-04 02:53:00
【问题描述】:

当您有一个在对象实例化时已知且之后不应更改的变量时,应使用只读字段。

但是,不允许从子类的构造函数中分配只读字段。 如果超类是抽象的,这甚至不起作用。

有没有人能很好地解释为什么这不是一个好主意,或者缺乏 C# 语言?

abstract class Super
{
    protected readonly int Field;
}

class Sub : Super 
{
    public Sub()
    {
        this.Field = 5; //Not compileable
    }
}

PS:您当然可以通过在超类的受保护构造函数中分配只读字段来达到相同的结果。

【问题讨论】:

  • 编译器错误也不准确:Error 68 A readonly field cannot be assigned to (except in a constructor or a variable initializer)

标签: c# inheritance variable-assignment readonly restriction


【解决方案1】:

我能看到的唯一原因是因为“它就是这样设计的”,根据spec

对只读字段的直接分配只能作为其中的一部分发生 声明或在实例构造函数或静态构造函数中 同一班。

只读的关键是它不能被改变,如果派生类可以修改,那么这将不再是真的并且会违反封装(通过修改另一个类的内部)。

【讨论】:

  • 确实如此。但是它仍然不适合抽象类吗?也许是因为可能有多个子类。
  • 这可能是不恰当的,也许我们永远不会知道做出该设计决定的确切原因。
  • 我不明白为什么它不适合抽象类,因为它们可以有构造函数,因此只读字段可以工作。
【解决方案2】:
public class Father
{
    protected readonly Int32 field;

    protected Father (Int32 field)
    {
        this.field = field;
    }
}

public class Son : Father
{
    public Son() : base(5)
    {

    }
}

你可以试试这样的东西!

【讨论】:

  • 是的,我在我的问题中提到了这一点 :) 此外,alexm 大约 10 分钟前发布了完全相同的答案。
  • 这不是编辑,但没关系!这是一个巧妙的解决方法
  • 正是我正在寻找的解决方案。这只是吹毛求疵,但我会稍作修改以加强只读性(不是一个词):在 Son 类中声明一个变量“private readonly Int32 CONCRETE_FIELD = 5”。然后对于构造函数 "public Son() : base (CONCRETE_FIELD) { }.
【解决方案3】:

我认为主要原因是所有 .NET 语言实现的额外复杂性

另外,总有一个简单的解决方法:

 abstract class Super
 {
     protected readonly int Field;

     protected Super(int field)
     {
          this.Field = field;
     }
 }


class Sub : Super {
   public Sub():base(5)
   {
   }

}

【讨论】:

    【解决方案4】:

    我将通过 C# 中的抽象/虚拟属性对此进行建模。

    abstract class Super {
      protected abstract int Field { get; }
    }
    
    class Sub : Super {
      protected override int Field { get { return 5; } }
    }
    

    在我看来,这比使用包含每个只读字段作为参数的构造函数更好的解决方案。一方面是因为编译器也能够内联 this 并且因为构造函数解决方案在派生类中看起来像这样:

    class Sub : Super {
      public Sub() : base(5) { } // 5 what ?? -> need to check definition of super class constructor
    }
    

    如果您已经有一个采用单个 int 值的构造函数,这也可能不起作用。

    【讨论】:

      【解决方案5】:

      我更喜欢在超类中使用受保护的构造函数(如 alexm 所述),与 xml cmets 一起使用。 这应该可以消除 DonAndre 在代码注释中所说的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-17
        • 1970-01-01
        • 1970-01-01
        • 2021-04-02
        • 1970-01-01
        相关资源
        最近更新 更多