2009-09-14 3 views
7
public class ClassA 
{ 
    public static readonly string processName; 
} 

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

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

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

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

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

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

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

ответ

14

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

Предположим, что у вас есть другой класс, производный от 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") 
    { 
    } 
} 
+0

, но это работает только с переменными экземпляра, которые на самом деле не достигают желаемого –

Смежные вопросы