Visual Basic .NET still supports late binding. Late binding is what happens when the type of an object is general and the instance of an object is specific. For example, if you declare a variable as an Object type and initialize a Button control, assigning the Button instance to the Object variable, you are using late binding. Late binding is supported through Reflection. Listing 4.1 offers an example.
Listing 4.1 An Example of Late Binding Using Reflection
Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim C As Object C = New Button() C.Text = "Test" C.Bounds = CType(sender, Control).Bounds C.Location = New Point(C.Location.X, C.Location.Y + C.Size.Height + 10) AddHandler CType(C, Control).Click, AddressOf Button1_Click Controls.Add(C) End Sub
Listing 4.1 is an event handler for a control named Button1 . The first line of code in the event handler declares a variable that is typed as an object. The object C is initialized as a button. The button's Text property is set. The bounding region of the button is defined. A Click event handler ”this handler for convenience ”is associated with the dynamic button, and the button is added to the form's Controls collection.
There are several problems with the code in Listing 4.1. The first one will be obvious if you type the code in Visual Studio .NET: Intellisense doesn't know the type of C and as a result cannot offer any assistance while we are programming. A second obvious problem is all the muddled code we have to write to access some of the members of the button. One example of muddled code is where we have to dynamically cast the sender argument reflecting the button we clicked as a Control to access the Bounds property. A second example of muddled code is the dynamic typecast to add the event handler (on the line with AddHandler ). We can't even assign the event handler using late binding without a type conversion. (Type conversions are performed with CType .)
Late binding is supported but is an anachronistic behavior that should be left in the past. Late binding permits the use of variables without declaring them and without dynamically casting types, although this can lead to slower running code and runtime errors.
Visual Basic programmers have been relying on late binding for quite some time, but it has always been a bad practice. Relying on weak type checking, late binding, and implicit code writing results in buggy , convoluted code.
At the top of every source code module, place the Option Strict On statement. This will prevent you from using weakly typed practices. If Option Explicit is Off , you can write code like this:
Dim MyCustomer = New Customer()
Unfortunately, the type of object is implicit and you will be using late binding. Option Strict On will force you to write the more explicit form of declaration and construction.
Dim MyCustomer As Customer = New Customer()
When you use Option Strict On the IDE will find unsupported, weakly typed code. You will have to declare the types of variables. Also, VB .NET will catch instances where your code is performing conversions that might lead to lost information, such as implicitly assigning the result of a function that returns a Long value to an Integer variable. Listing 4.2 demonstrates the slightly leaner, revised code for Listing 4.1.
Listing 4.2 A Revised Version of Listing 4.1 That Uses Strict Type Checking
Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim NewButton As Button = New Button() NewButton.Text = "Test" NewButton.Bounds = CType(sender, Control).Bounds NewButton.Location = New Point(NewButton.Location.X, _ NewButton.Location.Y + NewButton.Size.Height + 10) AddHandler NewButton.Click, AddressOf Button1_Click Controls.Add(NewButton) End Sub
The revised code is almost the same length as the original code. By using verbose code you will add extra lines to declare variables, but you will avoid confusion, get the benefit of Intellisense, and not have to perform as many type conversions.
Notice that we still have to cast the sender parameter to a control to access the Bounds property of the sender parameter. (Recall that the sender parameter represents the object that invoked the event handler.) With sender , the .NET developers made a judgment call: Using a generic type for the event handler parameter meant they had to write many fewer event handlers, resulting in a smaller framework. Had Microsoft defined event handlers that took a specific kind of Control argument, they would have had to define custom event handlers for all the controls that currently exist and those yet to be created. Clearly doing so is untenable and would be impossible to manage.