Saturday, January 12, 2008

Static Members in Generic Classes

The other day I and Alessandro talked about how static members behave in generic classes. This might be blatantly obvious for most people but might cause some confusion for others. Imagine having a generic class of the following nature:

public class MyClass<T>
{
    private static string text = "uninitialized";

    public static string Text
    {
        get { return text; }
        set { text = value; }
    }
}

Now you're calling for example MyClass<string>.Text = "string"; — What do you think MyClass<int>.Text contains after this? Yup, it still contains the "uninitialized" string. This is due to the fact that at runtime native code is produced specifically for every type. In a sense you could think that there are two separate copies of the generic class, MyClass of string and MyClass of int which both have their own separate static members.

What if you actually wanted generic classes regardless of the type to share their static members? This is easily achieved by writing a separate static class and making the static members in the generic class act as wrappers for the members of the static class:

public class MyClass<T>
{
    public static string Text
    {
        get { return MyClassStatic.Text; }
        set { MyClassStatic.Text = value; }
    }
}

internal static class MyClassStatic
{
    private static string text = "uninitialized";

    public static string Text
    {
        get { return text; }
        set { text = value; }
    }
}

Now both MyClass<string>.Text and MyClass<int>.Text would refer to the same string.