Присвоение статическому полю только для чтения базового класса - PullRequest
9 голосов
/ 14 сентября 2009
public class ClassA
{
    public static readonly string processName;
} 

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

Я получаю сообщение об ошибке при компиляции вышеуказанного кода C #.

Ошибка говорит - «Статическое поле только для чтения не может быть назначено (кроме как в статическом конструкторе или инициализаторе переменной)»

Но я назначаю его в статическом конструкторе.

Необходимость такой статической переменной заключается в том, что базовый класс имеет методы, которые используют эту переменную, но производные классы и базовый класс должны иметь разные значения для этой переменной. Но значение является постоянным для всех экземпляров соответствующего класса. Оно должно быть доступно только для чтения, потому что оно нигде не должно изменяться.

В чем ошибка в приведенном выше коде? (Если таковые имеются), кажется, я не могу их обнаружить. Сообщение об ошибке не помогает. Поскольку я не делаю ничего плохого согласно этому.

Если есть ошибка, как я могу реализовать эту функцию? Я знаю простой обходной путь - сделать его переменной экземпляра и назначить им разные значения в производных классах. Но в этом нет необходимости, поскольку значение является постоянным для всех экземпляров соответствующего класса.

Ответы [ 3 ]

15 голосов
/ 14 сентября 2009

Вы назначаете в неправильный статический конструктор. Он может быть назначен только в статическом конструкторе для типа, объявившего переменную .

Предположим, у вас есть другой класс, производный от ClassC, который делает то же самое - в итоге вы перезаписали бы переменную, которая предназначена только для чтения. Здесь есть одиночная статическая переменная, однако у вас есть много производных классов.

Один из ответов - избегать использования статической переменной , но помещать виртуальное свойство в базовый класс и заставлять каждый производный класс переопределять это свойство для возврата различной константы:

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

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

По сути, вариант состоит в том, чтобы разделить «статические» биты на отдельную иерархию - фактически это звучит так, как будто вам нужен полиморфизм над типом, а не экземплярами, и это не поддерживается в .NET.

5 голосов
/ 14 сентября 2009

В вашем примере будет существовать только одно поле базового класса, и вы не можете иметь разные значения в одном поле. Кроме того, вы можете инициализировать readonly поля только в одном классе, но не в производных классах. Обходной путь мог бы определить универсальный класс как:

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

и используйте ProcessNames<DerivedClassType>.Value вместо. Очевидно, что значение будет общедоступным таким образом.

Однако вы должны убедиться, что определение поля в каждом производном классе в отдельности соответствует вашим потребностям и применять обходные пути только в том случае, если это не так.

1 голос
/ 14 сентября 2009

Есть много способов снять кожу с кошки. Вот еще один способ сделать это.

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")
    {
    }
}
...