Static polymorphism: possible or impossible?

It’s a well-known fact that there’s no such thing as a virtual static method in C#. So does this mean that “static polymorphism” is not possible?

Ha ha! Nope. I was toying around with this idea recently and came up with a funny little way of achieving… well, something like static polymorphism, anyway.

Here’s the basic idea. No, you can’t define a virtual static method. But what you can do is design an abstract generic base class with its type parameter constrained to only derived types. Like this:

public abstract class BaseClass<T> where T : BaseClass<T> { }

Huh? I bet you’re thinking. What does that accomplish? Right? I know you’re scratching your head! (OK, maybe you’ve thought of and/or encountered this before. Fine—but don’t spoil it for everyone else!)

With this odd-looking constraint, what we can do is give BaseClass<T> a static member of type T, while also defining virtual or abstract methods which T can or must override. Like this:

public abstract class BaseClass<T> where T : BaseClass<T>
{
    protected readonly static T s_instance;

    static BaseClass()
    {
        // This is the only way to instantiate a T object without resorting to a
        // where T : new() constraint, which would be pointlessly restricting.
        s_instance = (T)Activator.CreateInstance(typeof(T), true);
    }

    // This is a static method, but it's going to ACT like a abstract method...
    public static void DoSomething()
    {
        s_instance.DoSomethingInner();
    }

    // ...because THIS is an abstract method!
    protected abstract void DoSomethingInner();
}

Pretty sneaky, huh?

Now, in case you didn’t quite follow what’s going on there (it is admittedly a very weird design), allow me to explain. BaseClass<T> is abstract; this much we know already. But it includes a static member of type T; and this type must inherit from BaseClass<T>; so where we’ve defined the DoSomethingInner method as abstract, we’ve effectively “polymorphized” (is that a word? no… but it ought to be) the behavior of the static method DoSomething, since this is passing a call directly to our static T member.

Let’s make this a bit more concrete by actually defining a couple of derived classes.

public sealed class DerivedClassA : BaseClass<DerivedClassA>
{
    // There's really no reason to instantiate this class directly;
    // we only want it for our precious static polymorphism.
    private DerivedClassA()
    { }

    protected override void DoSomethingInner()
    {
        Console.WriteLine("Greetings from DerivedClassA!");
    }
}

public sealed class DerivedClassB : BaseClass<DerivedClassB>
{
    // Same comment as above.
    private DerivedClassB()
    { }

    protected override void DoSomethingInner()
    {
        Console.WriteLine("DerivedClassB says hello!");
    }
}

You can kind of see what I’m doing at this point, yes? But now for the real test: does it work?

class Program
{
    public static void Main(string[] args)
    {
        DerivedClassA.DoSomething();
        DerivedClassB.DoSomething();
    }
}

Output:

Greetings from DerivedClassA!
DerivedClassB says hello!

Hot dog! Static polymorphism (kind of)!

I know, I know. So cool, right? No? Bueller?

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: