Try Catch Differences between VB.Net and C#
I’ve been extremely busy since coming back from Vegas, and even caught a little flack for not posting more quality stuff (and I agree, the quality isn’t there at the moment, but just wait until you see what I’ve been working on).
I ran across this little tidbit a couple weeks ago, and I wasn’t going to post it because I didn’t want to start another VB.Net versus C# thread, but I think it shows some of things done in the name of backward compatibility with VB6 which are helping kill a perfectly good language (VB.Net). I’ve got a bunch of other stuff that VS.Net does to “help” the VB.Net programmer, but only succeeds in making it hard for them to produce enterprise ready code, but this “flaw” is in the complier not the IDE.
My currently client has requested that the code be done in VB.Net, so I’m living a world trying to make VB.Net adhere to the same coding styles as C# (no VB only functions, using namespaces, no BAS files, good OO and Domain Driven Design (well sort of)) and fighting the IDE the whole way. I was disassembling one of our libraries and noticed a reference to VisualBasicMicrosoft.VisualBasic even though I specifically removed the default import of that namespace. I was curious as to why that was happening and noticed that it was only in the Try Catch statements. I thought that maybe it was something I was doing so I created 2 projects, one in C# and one in VB.Net, with one class, and a simple Try Catch in each
C#
using System;
public class Class1
{
public Class1()
{
try
{
Array a;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw (ex);
}
}
}
VB.Net
Imports System
Public Class Class1
Public Sub New()
Try
Dim a As Array
Catch ex As Exception
Console.WriteLine(ex.Message)
Throw (ex)
End Try
End Sub
End Class
You would think that both sets of code would compile down to the same IL, but they don’t.
C# IL
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 23 (0x17)
.maxstack 2
.locals init ([0] class [mscorlib]System.Array V_0,
[1] class [mscorlib]System.Exception ex)
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
.try
{
IL_0006: leave.s IL_0016
} // end .try
catch [mscorlib]System.Exception
{
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: callvirt instance string [mscorlib]System.Exception::get_Message()
IL_000f: call void [mscorlib]System.Console::WriteLine(string)
IL_0014: ldloc.1
IL_0015: throw
} // end handler
IL_0016: ret
} // end of method Class1::.ctor
VB.Net IL
.method public specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 29 (0x1d)
.maxstack 2
.locals init (class [mscorlib]System.Array V_0,
class [mscorlib]System.Exception V_1)
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
.try
{
IL_0006: leave.s IL_001c
} // end .try
catch [mscorlib]System.Exception
{
IL_0008: dup
IL_0009: call void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::SetProjectError(class [mscorlib]System.Exception)
IL_000e: stloc.1
IL_000f: ldloc.1
IL_0010: callvirt instance string [mscorlib]System.Exception::get_Message()
IL_0015: call void [mscorlib]System.Console::WriteLine(string)
IL_001a: ldloc.1
IL_001b: throw
} // end handler
IL_001c: ret
} // end of method Class1::.ctor
The VB.Net IL has one distinct addition to the IL within the Catch block there is a call to the VisualBasic dll, SetProjectError. Why would the VB Team add this call to their compiler? Backward Compatibility with VB6. As per Niklas (from the VB Compiler team:
“The extra two calls are there to support the "On Error" language feature that was retained to make it easier to upgrade from VB6 to VB.NET. … they only cost you time (and very little) if an exception actually happens. The time for the two calls is minor compared to the overhead of propagating exceptions.”
My problem with this is that you get this even if you are not using the old Or Error syntax. There is no reason why this can’t be a compiler option, or even better yet, let the compiler figure out is On Error is used and act accordingly. Because C# is not (currently) hindered by backward compatibility, it can avoid such issues (for now). I know this really isn’t that big of a deal, in terms of performance, it is just a VB mindset issue that helps to promote the idea that VB.Net is a second class language (which is re-enforced by little things like this).
[Corrected the VB IL code, since it was compiled with the debug option]
The preceding blog entry has been syndicated from the DonXML Demsak’s All Things Techie Blog. Please post all comments on the original post.