20

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

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

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

abstract class Super
{
    protected readonly int Field;
}

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

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

4

5 回答 5

13

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

对只读字段的直接赋值只能作为该声明的一部分发生,或者在同一类的实例构造函数或静态构造函数中发生。

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

于 2011-10-09T20:56:21.883 回答
11
public class Father
{
    protected readonly Int32 field;

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

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

    }
}

你可以试试这样的东西!

于 2011-10-09T20:59:51.633 回答
2

我将通过 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 值的构造函数,这也可能不起作用。

于 2011-10-09T21:05:21.673 回答
0

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

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

 abstract class Super
 {
     protected readonly int Field;

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


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

}

于 2011-10-09T21:00:26.677 回答
0

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

于 2012-04-11T18:18:38.517 回答