给基类的静态只读字段赋值

9
public class ClassA
{
    public static readonly string processName;
} 

public class ClassB : ClassA
{
    static ClassB()
    {
        processName = "MyProcess.exe";
    }
}

在编译以上C#代码时,我遇到了一个错误。

错误信息为--“静态readonly字段无法被分配(除非在静态构造函数或变量初始化器中)”。

但是我是在静态构造函数中进行赋值的。

需要这样一个静态变量的原因是,基类有使用此变量的方法,但派生类和基类必须具有不同的值。但是该值在各自类的所有实例中都是常量。它必须是只读的,因为不能从任何地方更改它。

以上代码是否存在错误?(如果有的话)我似乎无法发现其中的错误。错误信息没有提供帮助。因为按照错误提示所说的,我并没有做错什么。

如果存在错误,那么如何实现这个功能呢?我知道一个简单的解决方法是将其作为实例变量,并在派生类中为它们分配不同的值。但这是不必要的,因为该值在各自类的所有实例中都是常量。

3个回答

15

虽然你正在静态构造函数中进行赋值,但是你选择了错误的静态构造函数。它只能在声明变量的类型的静态构造函数中赋值。

假设您有另一个从ClassC派生出来的类也执行同样的操作-您最终会覆盖该变量,而该变量应该是只读的。无论您有多少个派生类,这里都只有一个单一的静态变量。

一个解决方法是避免使用静态变量,而是在基类中放置一个虚拟属性,并使每个派生类重写该属性以返回不同的常量:

public class ClassA
{
    public virtual string ProcessName { get { return "ClassAProcess"; } }
} 

public class ClassB : ClassA
{
    public override string ProcessName { get { return "MyProcess.exe"; } }
}

基本上,你的选择是将"静态"位分离到一个单独的层次结构中 - 实际上听起来像是你想要对类型而不是实例进行多态性,而这在.NET中不受支持。


1
没错!“类型上的多态性”。我觉得这个说法再恰当不过了。感谢您指出它在.NET中不受支持。 - Poulo

5

在你的例子中,只会存在一个字段,即基类的字段,并且你不能在单个字段中有不同的值。此外,你只能在同一类中初始化readonly字段,而不能在派生类中初始化。一个解决方法可以是定义一个泛型类,如下所示:

static class ProcessNames<T> {
   public static string Value { get; set; }
}

使用ProcessNames<DerivedClassType>.Value代替。这样做,该值将以公共方式访问。

但是,您应该检查在每个派生类中单独定义字段是否符合您的需求,只有在不符合时才采用解决方法。


1

有很多种方法可以解决这个问题。这里是另一种你可以尝试的方法。

public class ClassA
{
    public string ProcessName{ get; private set;}

    public ClassA()
    {
        ProcessName = "ClassAProcess";
    }

    public ClassA(string processName)
    {
        ProcessName = processName;
    }
}

public class ClassB : ClassA
{
    public ClassB() : base("ClassAProcess")
    {
    }
}

但是这仅适用于实例变量,这并没有真正实现想要的目标。 - Trevor de Koekkoek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接