The Conservative Nature of VB (Part 2) – Late Binding
I am now going to go into the next part of looking configuration of the warning options for the compiler. In the previous post I spoke about the warning configurations and specifically the one for implicit conversion.
Late binding has been a stable of Visual Basic since the early days and in ASP it was the only way one could create objects. Now in the old days late binding provided an ability to create instances of objects using a text value.
What is Late Binding? It is the nature of binding the object to the instance at the very last possible moment, before execution. Early Binding, the compile knows about the object, its methods and members and it can resolve this, perform optimisation if needed. But Late Binding, the compiler only sees text, it knows it can’t do anything with it until it is run and the process of calling the COM process invokes this and verifies if the component exists.
Even if the object specified is incorrect, you will not know about it until an instance is being created. Then in the examples I am using, if you get the class wrong you will then see an “Cannot create ActiveX component.” error, which once again I am sure most VB programmers has seen in their life.
Dim myObject = CreateObject("Scripting.FileSystemObject")
This is the example I am talking about. I am sure most VB programmers who have been programming in VB since before .NET would be familiar with this syntax. But putting this code in doesn’t cause anything happen.
So, this configuration item enables the environment/compiler to report on occurrences of late binding and report them to you. But there is one instance it can’t report to you which I will get to.
Take the following code;
Dim myObject As Object = CreateObject("Scripting.FileSystemObject") For Each tempName As Object In myObject.Drives Console.WriteLine(tempName.DriveLetter) Next
Fairly simple code, if you have used the file system object before you would recognise this.
That code, with late binding Warnings on, will display the following warnings. Note, there is also an implicit conversion happening but I have turned off these being reported.
The message displays as such. Late bound resolution, runtime errors could occur. Thankfully in this instance they don’t happen and if in a console application it will simply write the driver letters to the console window. But what about;
Dim myObject As Object = CreateObject("Scripting.FileSystemObject") For Each tempName As Object In myObject.Drives Console.WriteLine(tempName.Name) Next
Doesn’t look out of place, getting the drives putting the name to the console. But Name isn’t a valid member of the Drive object. So, the compiler tells me there is a problem with the resolution and an error could occur. Run it and ;
Unhandled Exception: System.MissingMemberException: Public member ‘Name’ on type ‘Drive’ not found.
Yes, not a lot we can do other than fix it. So, should I have it as an error or a warning. Well for one, I would say you could turn it off as in my opinion we shouldn’t be late binding. There is only a small number of instances where late binding is acceptable, scripting when objects have no type and for application add-ins where they are written for applications and are loaded using a binding reference stored as text. But even in the latter scenario there are other ways to do this as well.
So my recommendation is, get out of any habit you have of late binding and import your objects, add references to COM components using interop. There should be no late binding references in there. If unsure, switch all other warning options to None except Late Binding and see what comes up.
NOTE: The IDE has some wonderful features, one of which is IntelliSense. Late binding removes this feature create a new Console application and put in the code from listing 2 (I have realised I do not name my listings, mmm, maybe I should.). If you remove DriveLetter and the period and put a . down, you will see one thing, a drop down that contains the available members for Object.
Imports Scripting Module Module1 Sub Main() Dim myObject As New FileSystemObject() For Each tempName As Drive In myObject.Drives Console.WriteLine(tempName.DriveLetter) Next End Sub End Module
Now, using the same project add a reference to the COM component Microsoft Scripting Runtime. Include the import statement and using the code above, and you will see the drop down menu from tempName shows a great many more things.
The dropdown on the left is the Drive drop down members, the one on the right is the Object. Not only that, you get the nice help as well.
So, this helps as you know it returns a string and is ReadOnly. Handy. I know which one I would prefer.