所以我有一个有很多孩子的基类。此基类定义一些具有默认值的只读属性和变量。这些可能会有所不同,具体取决于孩子。
Readonly属性/字段允许您更改构造函数内部变量的值以及定义,但不能更改其他地方。如果我尝试在子类的构造函数中更改继承的只读变量的值,我会得到一个'readonly变量只能在构造函数中赋值'错误。为什么这样,如果没有反射,我该如何解决这个问题呢?
我的意图:允许用户通过脚本进行扩展,他们只能更改某些字段。
答案 0 :(得分:22)
原因是您只能在该类的构造函数中分配 readonly 字段。
根据{{3}}(强调我的):
当字段声明包含只读修饰符时,声明引入的字段的赋值只能作为声明的一部分或同一类的构造函数中的 。
要解决此问题,您可以在基础中创建一个受保护的构造函数,该构造函数接受readonly属性的参数。
一个例子:
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)
{}
}
}
答案 1 :(得分:8)
您可以使用虚拟仅获取属性来获取您正在寻找的确切行为。
public class BSE
{
virtual public int Prop
{
get
{
return 6;
}
}
}
public class Derived : BSE
{
public override int Prop
{
get
{
return 10;
}
}
}
字段超出了继承和重载模型的范围,不应用于提供多态功能。
答案 2 :(得分:7)
至于为什么会这样,请参阅C# constructor execution order,了解每个类的只读字段何时初始化/可初始化。
答案 3 :(得分:3)
您可以将属性与public get accessor和protected set accessor一起使用。派生类可以设置此属性的值。
一个例子:
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 int I { get; protected set; }
public Base()
{
I = 42;
}
}
class Child : Base
{
public Child()
{
I = 43;
}
}
}
答案 4 :(得分:0)
这在设计上是不可能的。尝试将值传递给protected
基类构造函数