Late Binding - Myths and Reality
Written by Mike James   
Friday, 05 July 2024
Article Index
Late Binding - Myths and Reality
Dynamic C#
Inheritance and Conditional Casting
Real late binding


We All Know The Type

When you see a late binding example of this sort you have to try to imagine that you really don’t know the type being used at run time at design time – this is the whole point of late binding.

But wait a minute.

Suppose you accept this as the absolute truth, that we don’t know the type until run time.

How can you possibly know what members to expect?

How can you fill in the missing “Method1” specification if you really don’t know the type that is being used until run time?

In fact what use to you is an instance of an unknown type?

The fact of the matter is that you must know what the run time type is at design time to write any code that makes use of the object, even if you are using reflection.

To be more precise you have to know the type is at least a given class or any of its sub-classes because you need to know that a minimal set of methods and properties exist to be able to make use of them. That is it doesn't matter if the class has other methods than "Method1" because you aren't going to call them but it must have a "Method1" if you are going to avoid a runtime error.

If this is the case then why not take the same approach to the inputs as you do to the output. The object that Method1 returns is actually an int and a down cast from object to int solves the problem of using this “late bound” type completely.

So why not use a cast for the method call?

For example the following very simple code achieves the same result reflection or dynamic type:

int count =((Class1)late).Method1("Hello World");

As we know that late is actually an instance of Class1 we simply cast to that type and use the method we know it has. Notice that this works even if the object is a sub-class of Class1.

What is more, you even get the advantage of IntelliSense prompting to select the method. Of course if we get it wrong and late isn’t of type Class1, or if Class1 doesn’t have a Method1, then we generate a run time error but then so do other approaches to late binding.

It is also very easy to make sure that no runtime error actually occurs using:

Class1 temp = late as Class1;
 int count = temp.Method1("Hello World");
 int count=0;

The as operator casts to the type if it can or returns a null reference if it can’t.

You could also claim that this method of late binding is strongly typed. You state clearly what the expected run time type of the object is and what happens if you are wrong.



Conditional Casting

At this point you are probably thinking that I’m cheating.

In real late binding you really cannot know what the type is without using reflection to determine the runtime type.

True enough but, as the earlier argument indicates, the run time type of a late bound instance has to be one of a small number of possibilities, otherwise you couldn’t actually write the code at design time to handle it.

In fact there is another alternative which allows there to be an unlimited number of alternatives but I’ll come back to this in a moment.

For example, you might have the possibility that there are two classes, Class1 and Class2 with Method1 and Method2 respectively and which one is late bound is arbitrary. Such an example usually needs reflection-based late binding. In fact it is just as simple to handle using casting, but this time conditional casting.

First introduce Class2 to the example:

class Class2{
 public string Method2() {
  return "Hello Later";

Its Method2 has a different signature and return type but this doesn’t make a great deal of difference.

We need a suitable mechanism for generating a type that I can’t possibly know until run time.

Randomly creating either Class1 or Class2 seems to fit this bill:

object late;
Random rnd=new Random();
if (rnd.NextDouble() < 0.5){
 late = new Class1();
 late = new Class2();

Now late references either Class1 or Class2 with a 50% probability of either.

Of course the solution to the problem is to simply try to cast to Class1 or Class2 and call the method corresponding to the one that works!

Class1 temp1 = late as Class1;
 int count = temp1.Method1("Hello World");
 int count=0;

Class2 temp2= late as Class2;
 String message = temp2.Method2();
 String message="";

This code works and it doesn’t produce any run time errors even if late turns out to be a reference to something other than the two classes in question. So in practice it isn’t any worse than using reflection or dynamic and in that case you would still have to test to discover which of Class1 or Class2 you had at run time.

It is also reasonable to say that conditional casting is a more strongly typed approach than reflection because at each stage you are stating your run time type assumptions and what happens if you are wrong – it really is type-based.

Of course you can invent more logical and neater ways to code the general idea. For example:

if (late is Class1){
 int count = ((Class1)late).Method1("Hello World");
if (late is Class2){
 String message =((Class2)late).Method2();

Last Updated ( Friday, 05 July 2024 )