views:

302

answers:

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

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

I am getting an error while compiling the above C# code.

The error says -- "A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)"

But I am assigning it in a static constructor.

The need for such a static variable is that, the base class has methods that uses this variable, but the derived classes and the base class must have different values for this variable. But the value is constant across all instances of the respective class. It must be readonly because, it must not be changed by anywhere.

What is the error in the above code? (If there is any) I do not seem to be able to spot one. The error message is not helping. As I am not doing anything wrong according to it.

If there is an error, how can I implement this functionality? I know a simple workaround would be to make it an instance variable and assign them different values in the derived classes. But that is unnecessary as the value is constant across all the instances of the respective class.

+4  A: 

In your example, only a single field will exist, that of the base class and you can't have different values in a single field. Beside that, you can only initialize readonly fields in the same class, not in derived classes. A workaround could be defining a generic class like:

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

and use ProcessNames<DerivedClassType>.Value instead. Obviously, the value will be publicly accessible this way.

However, you should see if defining the field in each derived class separately fits your need and only resort to workarounds if it does not.

Mehrdad Afshari
+9  A: 

You're assigning in the wrong static constructor though. It can only be assigned in a static constructor for the type declaring the variable.

Suppose you have another class deriving from ClassC which does the same thing - you'd end up overwriting the variable, which is meant to be readonly. There's a single static variable here, however many derived classes you've got.

One answer is to avoid using a static variable but put a virtual property in the base class, and make each derived class override the property to return a different constant:

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

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

Basically option would be to separate the "static" bits into a separate hierarchy - effectively it sounds like you want polymorphism over the type instead of instances, and that isn't supported in .NET.

Jon Skeet
Exactly! "Polymorphism over the type". I don't think it could be more appropriately phrased. Thanks for pointing out that it is not supported in .NET.
Poulo
+1  A: 

There's many ways to skin the cat. Here's another way you can do it.

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