views:

362

answers:

3

Without any code in the subclasses, I'd like an abstract class to have a different copy of a static variable for each subclass. In C#

abstract class ClassA
{
    static string theValue;

    // just to demonstrate
    public string GetValue()
    {
        return theValue;
    }
    ...
}
class ClassB : ClassA { }
class ClassC : ClassA { }

and (for example):

(new ClassB()).GetValue(); // returns "Banana"
(new ClassC()).GetValue(); // returns "Coconut"

My current solution is this:

abstract class ClassA
{
    static Dictionary<Type, string> theValue;
    public string GetValue()
    {
        return theValue[this.GetType()];
    }
    ...
}

While this works fine, I'm wondering if there's a more elegant or built-in way of doing this?

This is similar to Can I have different copies of a static variable for each different type of inheriting class, but I have no control over the subclasses

+5  A: 

While this works fine, I'm wondering if there's a more elegant or built-in way of doing this?

There isn't really a built-in way of doing this, as you're kind of violating basic OO principles here. Your base class should have no knowledge of subclasses in traditional object oriented theory.

That being said, if you must do this, your implementation is probably about as good as you're going to get, unless you can add some other info to the subclasses directly. If you need to control this, and you can't change subclasses, this will probably be your best approach.

Reed Copsey
A: 

There's an alternative solution which might or might not be better than yours, depending on the use case:

abstract class ClassA
{
    private static class InternalClass<T> {
        public static string Value;
    }
    public string GetValue()
    {
        return (string)typeof(InternalClass<>)
              .MakeGenericType(GetType())
              .GetField("Value", BindingFlags.Public | BindingFlags.Static)
              .GetValue(null);
    }
}

This approach is used in EqualityComparer<T>.Default. Of course, it's not used for this problem. You should really consider making GetValue abstract and override it in each derived class.

Mehrdad Afshari
A: 

This is a little different than what you're asking for, but perhaps accomplishes the same thing.

    class Program
{
 static void Main(string[] args)
 {
  Console.WriteLine((new B()).theValue);
  Console.WriteLine((new C()).theValue);
  Console.ReadKey();
 }
}

public abstract class A
{
 public readonly string theValue;

 protected A(string s)
 {
  theValue = s;
 }
}

public class B : A
{
 public B(): base("Banana")
 {
 }
}

public class C : A
{
 public C(): base("Coconut")
 {
 }
}
Matthew Sposato
ste