Microsoft lied!

Okay, so this post will probably blow my MVP nominations for this year and for most of anyone out there, it’s nothing new but dammit, Microsoft lied to us!

With the introduction of .NET, one of big claims I kept hearing was about how all the code was compiled down to IL (Intermediate Language) and the CLR, the .NET runtime, would process everything the same way because it was the same code. Gone was the holy wars of VB being slow, C++ being bloated and, C being licketity split fast. Now everything ran the same because it was. Or so they said.

Today I spent the better part of 8 hours in a “advanced” .NET debugging course. Except for the last 1/2 hour when we actually were given a problem to solve, the rest was going through labs where you typed something and watched what the result was. Type in “C-A-T”. Do you see a CAT? You typed “C-A-T”. Yeah. Anyways, rather than screw around with one of the labs we decided to use our new found knowledge of the IL code that .NET is based on and poke around a bit.

We created two applications, side by side, with exactly the same code except one was written in VB.NET and the other was C#. Two applications (TheApp) with a class (TheClass), a method (TheMethod, you’re seeing a pattern here right?), and a variable (TheVariable for those of you that haven’t been following along). Given our knowledge of what Microsoft has told us, the two, when compiled would look exactly the same to .NET

Nope.

Here’s the IL dump from the C# version:


.method public hidebysig instance void TheMethod(string theParameter) cil managed

{

// Code size 8 (0x8)

.maxstack 2

IL_0000: ldarg.0

IL_0001: ldarg.1

IL_0002: stfld string TheApp.TheClass::_theVariable

IL_0007: ret

} // end of method TheClass::TheMethod

And here’s the VB.NET version:


.method public instance void TheMethod(string theParameter) cil managed

{

// Code size 10 (0xa)

.maxstack 8

IL_0000: nop

IL_0001: ldarg.0

IL_0002: ldarg.1

IL_0003: stfld string TheApp.TheClass::_theVariable

IL_0008: nop

IL_0009: ret

} // end of method TheClass::TheMethod

Hmmm. One of these things is not like the other. hidebysig? In the C# version but not VB.NET. Code size is different (but not much). Wow, look at that stack! VB is 4x the size of the C# one. And what the hell are those “nop” things? In assembler, nop is a non-instruction. Basically tell the computer to do nothing (or as close to nothing as a computer can get). So VB.NET has graciously added a few of those in our code.

Just for kicks another bud built the J# version. Hey, it all compiles to the same IL code right? Uh-huh.


.method public hidebysig strict virtual instance void

TheMethod(string theParameter) cil managed

{

// Code size 10 (0xa)

.maxstack 2

IL_0000: ldarg.0

IL_0001: ldarg.1

IL_0002: stfld string TheJSharpApp.TheClass::theVariable

IL_0007: br.s IL_0009

IL_0009: ret

} // end of method TheClass::TheMethod

At least the “nop” commands are gone but they’re magically replaced with a br.s to IL_0009 (whatever that is). Gotta love that J#.

So let’s do the math. A 1 line method in a class produces 3 operations in C#, 4 in J#, and 5 in VB.NET. Using Chewbacca Defense logic (and math), if I had say an application that had enough classes with enough methods the computer would spend 40% more time churning with the VB.NET app than it would C#. Does that sound the same to you kids?

So Microsoft lied to us and here it is in black and white. C# is better than VB.NET! Let the holy wars begin!