2011-05-17 80 views
16

所以我有一个有很多孩子的基类。这个基类定义了一些只读属性和具有默认值的变量。这些可以是不同的,这取决于孩子。为继承的只读字段赋值?

只读属性/字段允许您更改构造函数,也定义内部变量的值,但在其他地方。如果我尝试在子类的构造函数中更改继承的只读变量的值,我会得到'只能在构造函数中分配的只读变量'错误。为什么是这样的,我怎样才能解决这个问题,没有反思?

我的意图:要允许用户扩展通过脚本,他们只能改变某些领域的一次。

+0

我有一个非常类似的问题,并得到了一个【答案】(http://stackoverflow.com/questions/42682527/eliminate-duplicate-c-sharp-property-bodies),让你做一个单一的分配成员。功能只读,并且所有样板代码都在一个位置。 – wizard07KSU 2017-03-09 02:27:18

回答

6

亚当有正确的答案。如果您担心它将占用的空间(构造函数中的参数数量?),那么您应该将其作为另一个不同解决方案的问题来解决:创建一个BaseConfig类,它包含所有这些属性,这就是所有需要传入。然后Base可以从BaseConfig的属性中分配所有只读字段,或者也可以让Base只保存一个BaseConfig类型的只读字段,并将其引用。

至于为什么这是,请参阅C# constructor execution order关于何时每个类的只读字段将被初始化/初始化。

+0

这让我有点难过;我希望能有一个非常好的方法来实现这一点,所以为我的引擎编写脚本将非常巧妙。好吧。一个BaseConfig类也可以工作,谢谢! – 2011-05-18 06:34:41

17

原因是您只能在该类的构造函数中指定只读字段。
根据the definition of readonly in the C# Reference(重点煤矿):

当字段声明包括只读改性剂,分配到由该声明引入的字段只能发生在同一类的构造函数的声明或的一部分

为了解决这个问题,你可以在基类中为受保护的构造函数设置只读属性的参数。

一个例子:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Base b = new Child(); 
      Console.WriteLine(b.i); 
      Console.Read(); 
     } 
    } 

    class Base 
    { 
     public readonly int i; 

     public Base() 
     { 
      i = 42; 
     } 

     protected Base(int newI) 
     { 
      i = newI; 
     } 
    } 

    class Child : Base 
    { 
     public Child() 
      : base(43) 
     {} 
    } 
} 
+3

此解决方案的唯一缺点是它不允许您计算要传递给基类的值。 – Kent 2016-01-22 04:49:39

+1

@Kent:通过在基类构造函数的参数列表中调用一个静态方法是可能的。请参阅http:// stackoverflow。com/questions/1651444 /修改参数值之前发送到基地构造函数 – ofthelit 2016-08-08 08:49:11

0

这是不可能通过设计。尝试值传递给一个protected基类构造函数

6

你可以让你通过使用虚拟仅获得性寻找的行为。

public class BSE 
{ 
    virtual public int Prop 
    { 
     get 
     { 
      return 6; 
     } 
    } 
} 
public class Derived : BSE 
{ 
    public override int Prop 
    { 
     get 
     { 
      return 10; 
     } 
    } 
} 

字段超出继承和重载模型,不应该用于提供多态特性。

+0

这听起来更像它;但它仍然是一个相当大的跳跃,从干净的'public readonly int number = 5'。 – 2011-05-18 05:41:17

+0

@Ruirize你正在给只读字段分配一个常量?这听起来像是滥用只读字段,您可能想使用虚拟属性。 – CodesInChaos 2011-05-18 06:27:56

3

您可以使用属性的公共get访问和保护的set访问。派生类可以设置此属性的值。

+0

一个例子可以帮助这里... – 2015-02-28 19:56:12