|Late Binding - Myths and Reality|
|Written by Mike James|
|Tuesday, 30 September 2014|
Page 1 of 3
Late binding in .NET – the accepted wisdom is that it’s complicated, advanced and VB does it better than C#. We explain that it’s easy and C# and VB are equally good at it and illuminate what is going on in other languages.
The concepts of late and early binding can be confusing, mainly because they aren’t really as different as they might first seem.
There is also a general belief that late binding in C# is sophisticated but hard work and in VB .NET less sophisticated but much easier.
There is a sense in which late binding is really isn’t any different from early binding – you could say it’s more about the state of mind of the programmer, but it’s high time to look in more detail at how it all works.
What is late about late binding?
When you work with a strongly typed language then early binding is the norm – indeed it might even be the only type of binding allowed.
The basic idea is that you declare the type of every variable you use within the code and this allows the compiler to check what you are writing for correctness. It can also allow the IDE to provide help by listing the methods and properties that you can use as in the Intellisense feature of Visual Studio.
Where early binding starts to show its limitations is when you need to write some code that deals with a range of data types.
If at this point you are thinking “generics” then yes but it’s still, in concept, early bound. If you express an algorithm as generic code all that happens is that early binding is deferred until you specify, at design time, the types to be used with the template. That is when you actually use a generic you have to specify the type it is working with at design time.
Late binding implies that the type of an object isn’t known until run time and this goes well beyond generic templates.
To clarify what is going on It is useful to change from thinking about variables or instantiated classes to “pointers” or more properly references to instances. The reason is that if you think about variables it is easy to conclude that you need to know the type of an object when the variable is declared because otherwise how would the system know what memory to allocate to store the object.
However if you have a pointer or a reference to an object the system doesn't need to know what it is referencing for practical purposes because a reference is a reference no matter what it references.
References have to be typed not for any practical implementation reason but because a decision has been made to enforce early binding.
This means that it is perfectly possible to have a pointer or reference to an instance of an unknown type – unknown that is at design time. To make use of the unknown type you have to discover its type at run time using some sort of dynamic type information.
In .NET this dynamic type information is supplied by the “reflection” classes. In fact the reflection classes provide facilities that go beyond simple late binding to allow you to create types and instances dynamically.
So the key idea in late binding is the use of a reference to an object whose type is only determined dynamically at run time.
In reality all objects are managed using references, even if they are early bound, so the only real difference is the programmer’s ignorance and hence compiler's ignorance of the type at design time.
This is a key observation – if the programmer knows the type then it’s early binding; if the programmer doesn’t know the type it’s late binding.
Let’s see what happens if we pursue this idea.
Late binding in action
So much for theory; it’s time for an example, and examples are always better the simpler they are. In the real world late binding usually occurs in some messy, complicated, way that obscures what is happening.
Let’s start with C#.
In this case we need a class with a single method to try things out:
Now we are going to create and use an instance of the class but we are going to "pretend" not to know its type.
As we don’t know its type we need an object variable to refer to the instance:
Clearly in this example the programmer does know the type of the instance stored in late at design time!
This is even more obvious when you write the instantiation as:
The compiler also knows the type of “late” at design time but C# it does its best to ignore this - i.e. it doesn't apply any type inference.
If you now write:
you will get a compile time error message which says that “object does not contain a definition for Method1” which is indeed true.
It is in this sense that it is said that C# doesn’t support automatic late binding.
The declared type of the reference to an object determines what methods and properties the object has irrespective of what methods and properties it actually has. This is enforced at design time by the compiler and it is what makes late binding seem impossible.
But don’t give up on it just yet - dynamic types introduced in C# 4 make it easy.
VB and late binding
Turning now to VB .NET, things are much simpler as long as we set:
For arguably good reasons VB feels a bit embarrassed about handling late binding so casually and insists that you explicitly turn it on.
If you do this then as long as you know the type of a class at design time the compiler will let you make use of it. For example, with the same definition of Class1 in VB we have:
with Option Strict set to Off this works; with it set to On it fails in exactly the same way that the C# does and generates a compile time error.
Of course if you make a mistake and late reference an instance that doesn’t have a Method1 then you get a runtime error.
This is the terrible disaster that both C# and Strict On are trying to save you from. Early binding means that you can avoid a runtime error generated by trying to call a method or access a property that doesn't exist.
Notice that the VB .NET approach is a bit like saying:
“I think that object is some type that has a method called Method1. If so call it. If not – oops!”
Hardly a strongly typed approach.
The dynamic type was introduced in C# 4 and it extends VB's way of doing things in Strict Off mode to C#.
Basically if you declare a reference to be dynamic then this is like declaring it to be object but you can attempt to use any methods or properties you care to.
For example, assuming the same class definitions as before you can write:
In this case the use of Method1 succeeds just like it does in VB in Strict off mode.
As in that case if the method or property that you try to use doesn't exist then the result is a runtime error.
Reflection based late binding
Suppose that in the C# example we really need to use late binding in a complex and sophisticated way.
Then the standard solution is to use reflection to dynamically discover the type and the other properties of the instance that we want to make use of.
The key to this is the Type class in the System.Reflection name space, so add:
The first thing we need is a type object representing the instance stored in late:
Next we need a parameter array containing the parameters we want to pass to the method we are about to call. In this case we need a single element containing the string:
With all of this set up we simply use the InvokeMember method:
This calls the specified member “Method1”, using its specified type, i.e. a public instance method, using default bindings belonging to the object referenced by late passing the parameters in param.
This all works very nicely but guess what happens if you try to access a member that doesn’t exist.
You generate a runtime error!
In this and other senses reflection-based late binding using either reflection or the newer dynamic type isn’t any better than the VB approach.
Also notice the strange double standards being applied to the late binding of the inputs - the method name and its parameters - and the rather more casual approach to the outputs - the object returned as a result.
Do we bother to use reflection to discover what the result is and to access it?
No, we simply cast it to an int because we know what type is it.
You can use exactly the same approach in VB .NET as the reflection classes are the same.
I have seen VB programmers use reflection in this way simply to avoid having to set strict to off – something they regard as an admission of defeat.
I think the simple “strict off” approach is far better it at least is honest about what is going on.
|Last Updated ( Tuesday, 30 September 2014 )|