Awhile back I was helping lead a team in developing a .NET SDK for all of our enterprise applications to use (common components, developer guidelines, standards, etc). Our shop is primarily VB, so that’s what we developed the shared components in. One of the topics we talked about was how to get developers to stop writing code the VB6-way, using such methods as CInt, UBound, Len, etc. These methods are part of the Microsoft.VisualBasic assembly and are really wrappers to underlying methods in the framework (for instance, UCase actually calls ToUpper). This assembly is imported by default when you create a new VB.NET project in Visual Studio. See it by viewing Project Properties and clicking Imports under Common Properties.
My initial thought was to just make sure all developers remove this assembly from the Imports in Project Properties. Simple enough, right? Well, not so fast.
To verify this, I created a sample VB.NET project with a single class that contains the following code:
Public Class MyClassLib
Public Sub MySub()
Dim s As String = “123“
Dim i As Integer = 789
s = CStr(i)
i = CInt(s)
End Sub
End Class
I then went to Project Properties and removed the import of the Microsoft.VisualBasic assembly. I half expected the little blue squiggly line to appear under the CStr and CInt methods, but to no avail. So then I compiled the project thinking that the compiler would catch the error at build time, but again, everything was fine. After this I began searching MSDN for clues, but couldn't really find anything other than the normal documentation for those methods. I happened to run ILDASM on the assembly and found this for the MySub method:
.method public instance void MySub() cil managed
{
// Code size 29 (0x1d)
.maxstack 1
.locals init ([0] int32 i, [1] string s)
IL_0000: nop
IL_0001: ldstr "123"
IL_0006: stloc.1
IL_0007: ldc.i4 0x315
IL_000c: stloc.0
IL_000d: ldloc.0
IL_000e: call string [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StringType::FromInteger(int32)
IL_0013: stloc.1
IL_0014: ldloc.1
IL_0015: call int32 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.IntegerType::FromString(string)
IL_001a: stloc.0
IL_001b: nop
IL_001c: ret
} // end of method MyClassLib::MySub
Notice the reference to Microsoft.VisualBasic for the two conversion methods. At this point I thought that maybe the VB.NET compiler was adding the library automatically behind the scenes. So then I compiled my project using the vbc from the command prompt and got this output:
C:\>vbc myclasslib.vb /out:myclasslib.dll /target:library /verbose
Adding file 'C:\Projects\MyClassLib\MyClassLib.vb'
Compiling...
Loading C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\mscorlib.dll.
Loading C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\Microsoft.VisualBasic.dll.
Building C:\Projects\MyClassLib\MyClassLib.vb.
Compilation successful
The second Loading step confirms that the VB.NET compiler is adding the Microsoft.VisualBasic library automatically (and there’s no way to stop it). I find this as a problem. It’s another thing Microsoft did to provide backwards compatibility with the legions of VB6 developers out there, which can be argued was the smart thing to do. But I would prefer to get all the VB6 developers learning to write “pure” .NET code, not a mix of VB6 and VB.NET code. Plus, I would like to have the option of explicitly removing the Microsoft.VisualBasic assembly if I know I don’t need it.
Did Microsoft do the right thing by always including this assembly at compile time? Yes and no. Yes because it allows VB6 developers to move to .NET much quicker. No because it comes at the risk of those same developers not understanding what’s really happening under the covers, thus also increasing the risk of VB6-type code living well into the life of a .NET application.
Print | posted on Tuesday, February 03, 2004 7:52 PM