Early vs. Late Binding
One of the strengths of VB has long been that we had access to both early and late binding when interacting with objects.
Early binding means that our code directly interacts with the object – knowing its data type ahead of time and thus being able to very efficiently interact with the object. Early binding allows the IDE to use IntelliSense to aid our development efforts and it allows the compiler to ensure that we are referencing methods that do exist and that we are providing the proper parameter values.
Late binding means that our code interacts with an object dynamically at run-time. This provides a great deal of flexibility since our code literally doesn’t care what type of object it is interacting with as long as the object supports the methods we want to call. Because the type of the object isn’t known by the IDE or compiler, neither IntelliSense nor compile-time syntax checking is possible – but in exchange we get unprecedented flexibility.
VB.NET continues this tradition, providing support for both early and late binding as we work with
our objects.
By default, all objects are early bound. The IDE and compiler enforce this as long as Option Strict On
is set, and this is the default. However, if we set Option Strict
Off
at the top of a source file (as discussed in Chapter 3), we open the door for late binding throughout the code in that file.
Use of the Object Type
Late binding occurs when the compiler can’t determine the type of object we’ll be calling. This level of ambiguity is achieved through the use of the Object
data type. A variable of data type Object
can hold virtually any value – including a reference to any type of object. Thus, code such as the following could be run against any object that implements a MyMethod
method that accepts no parameters:
Option Strict Off
Module LateBind
Public Sub DoSomething(obj As Object)
obj.MyMethod()
End Sub
End Module
If the object passed into this routine doesn’t have a MyMethod
method that accepts no parameters, then a run-time error will result. Thus, it is recommended that any code that uses late binding you should always provide error trapping:
Option Strict Off
Module LateBind
Public Sub DoSomething(obj As Object)
Try
obj.MyMethod()
Catch
‘ do something appropriate given failure to call the method
End Try
End Sub
End Module
While late binding is flexible, it can be error prone and it is slower than early bound code. To make a late bound method call, the .NET runtime must dynamically determine if the target object actually has a method that matches the one we’re calling, and then it must invoke that method on our behalf. This takes more time and effort than an early bound call where the compiler knows ahead of time that the method exists and can compile our code to make the call directly.
Late Binding and Reflection
The .NET Framework supports a concept known as reflection. This is the ability to write code that examines other .NET code to determine its composition. Reflection is supported by the System.Reflection
namespace.
Reflection allows us to write code that discovers the classes within an assembly and the methods, properties and events exposed by those classes. We can then use reflection to create instances of those classes and call those methods. This entire process can be very dynamic – much like late binding.
In fact, VB.NET uses reflection to implement late binding on our behalf. Rather than forcing us to write the code that uses reflection to find and invoke a method, VB.NET handles this for us when we use late binding coding techniques.
We could implement a limited form of reflection within VB6 by using the typelib
DLL. The functions in this DLL allowed us to dynamically discover the classes and methods in a COM DLL, and then invoke them. Of course COM components were described with IDL – a rather inaccurate description of the component. In .NET, assemblies are described by metadata that accurately describes each assembly, making reflection a much more robust solution.