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. 

No Comments