Late static binding in C#

The last couple of years I work in PHP, without that being my choice, and naturally I curse all the time about the lack of all those little things that are taken for granted in C#. Today, however, I am going to talk about  Late Static Binding, a feature of PHP 5.3 that does not exist in C#.

Late Static Binding, to be put simply, is the ability to override static functions. It is the equivalent of late dynamic binding, ie. the ability to override methods, which is a key feature of object oriented programming.

Let’s see an example.

// PHP Code:
class A {
  public static function GetName(){
    return 'A';
  }
  public static function SayHello(){
    return 'Hello from '.static::GetName();
  }
}

class B extends A {
  public static function GetName(){
    return 'B';
  }
}

A::SayHello();  // returns 'Hello from A'
B::SayHello();  // returns 'Hello from B'

This seems to be very natural. Had I used dynamic methods, that would have been straight forward, because dynamic methods are always late-bound. However, I want to use static functions. This is something that is not supported by many languages. In PHP, this behavior is possible with the use of the static:: scope, which is late-bound.

On the other hand, this is not possible in C#. Let’s translate the code, word by word:

// C# Code:
public class A {
  public static string GetName(){
    return "A";
  }
  public static string SayHello(){
    return "Hello from " + GetName();  // here is the problem
  }
}

public class B : A {
  public static string GetName(){
    return "B";
  }
}

A.SayHello();    // returns "Hello from A"
B.SayHello();    // returns "Hello from A"

Oops! The static function GetName() is early bound, which means that it is always resolved as A.GetName(), even if it is called from the static context of the class B.

A pattern to the rescue

The problem is simple. The base class does not know which is the current static context and it always assumes it to be A.

This can be solved with Generics. The current static context can be passed as a generic parameter to the base class, so the class A can become A<T>. The generic parameter T is the current static context. So the class B has to extend A<B> because we want all the the static calls to be bound to B.

However, adding a generic parameter to a class changes the class signature. In other words, A is not the same as A<T>. Yet, in C#, it is possible to have both! So, the class A has to extend A<A>, because we want all the static calls to be bound to A! Remember, that this is possible because A is not the same as A<T> and nothing forbids us from setting T to A.

Furthermore, the parameter T has the type A<T>, which means that it follows the interface of A<T>. That’s exactly what we want to achieve. All static function inside A<T> can be called from the static context of T. So, instead of calling GetName() which is early bound, we can call T.GetName().

All these may sound like a vicious circle, but the following code actually compiles and gives the solution we want.

 // C# Code:
public class A<T> where T : A<T> { // vicious but compiles
  public static string GetName(){
    throw new Exception("Not implemented");
  }
  public static string SayHello(){
    return "Hello from " + T.GetName();
  }
}

public class A : A<A> {  // cool, right?
  public static string GetName(){
    return "A";
  }
}

public class B : A<B> {
  public static string GetName(){
    return "B";
  }
}

A.SayHello();   // returns "Hello from A"
B.SayHello();   // returns "Hello from B"

So, the trick here was to separate the class into two parts. The first part will have a generic parameter which represents the current static context and will contain all the static functions. The other part will be the ordinary class which will continue to work as if nothing has changed.

Stay tuned, in the next post I am going to analyze a trickier example with more levels of inheritance.

Advertisements

5 thoughts on “Late static binding in C#

  1. Seems like a lot of hoops to jump through to redefine a method. Do you think it would ever be better to just use an interface and have A and B define different methods?

    • Late static binding is not about redefining a method, but about overriding it. This way, the base class A can call the code of the subclass B (or any other subclass), without even knowing its existence.

  2. Especially love it you managed to do it with just generics rather than the extensive Reflection classes

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