Title Image

Don Xml's Grok This

The home of Don Demsak
Welcome to Don Xml's Grok This Sign in | Help
in Search

This Blog

Syndication

Site Sponsors

DonXml's All Things Techie

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]

Published Monday, November 15, 2004 7:46 AM by donxml
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

TrackBack said:

November 15, 2004 7:52 AM

Karl said:

I've argued before that VB.Net ought to add a 3rd compilation option along the lines of explicit and strict, say "really strict" which would allow none of these bad backwards compatible things...like BAS, non-shortcircuit operators, returning values by function name instead of using "return", no support for on error resume next, and less/no hooks into the MS.VB namespace
November 15, 2004 8:30 AM

TrackBack said:

November 15, 2004 10:19 AM

Robert McLaws said:

You have a lot of "nop" instructions in there... are you compiling in Debug or Release mode?
November 15, 2004 10:38 AM

Don Demsak said:

Robert, Thanks I missed that and should have noticed it. I've updated the IL.

Don
November 15, 2004 11:09 AM

Daniel Moth said:

I was going to blog about this at some point - you beat me to it :-) BTW, the other difference is that VB catches Exception whereas C# catches Object...
November 15, 2004 1:14 PM

Dave said:

I also wrote about this a ways back here -

http://loudcarrot.com/Blogs/dave/archive/2004/02/03/147.aspx
November 15, 2004 1:53 PM

James Summerlin said:

This is cool, Don.

You make a point that I think needs to be heard more often. MS needs to stop bowing before the pressures of backward compatibility more often.

While backward compatibility is a good thing, to much of a good thing is not a good thing.

And we are at that point now.
James
November 15, 2004 2:35 PM

Chris said:

Jeffrey Rickter pointed out the differences in the following code, between C# and VB. The VB has these extra calls to CompilerServices.RuntimeHelpers::GetObjectValue(object).

OTOH, if we worry too much about these little things we would also not be using XML as too verbose. It is, but it's benefit out-weigh that.

C#

using System;
namespace SmallLib
{
public class Class1
{
static public void Main()
{ object o = 5;
o = m( o, o, o );
}
static public object m( object o1, object o2, object o3 )
{ return o1; }

public Class1()
{
}
}
}

C# IL

.method public hidebysig static void Main() cil managed
{
// Code size 17 (0x11)
.maxstack 3
.locals init (object V_0)
IL_0000: ldc.i4.5
IL_0001: box [mscorlib]System.Int32
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldloc.0
IL_0009: ldloc.0
IL_000a: call object SmallLib.Class1::m(object,
object,
object)
IL_000f: stloc.0
IL_0010: ret
} // end of method Class1::Main

VB

Public Class Class1
shared sub Main()
dim o as Object = 5
o = m(o, o, o)
end sub

Public Shared Function m(ByVal o1 As Object, ByVal o2 As Object, ByVal o3 As Object) As Object
Return o1
End Function

End Class

VB IL

.method public static void Main() cil managed
{
// Code size 37 (0x25)
.maxstack 3
.locals init (object V_0)
IL_0000: ldc.i4.5
IL_0001: box [mscorlib]System.Int32
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: call object [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::GetObjectValue(object)
IL_000d: ldloc.0
IL_000e: call object [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::GetObjectValue(object)
IL_0013: ldloc.0
IL_0014: call object [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::GetObjectValue(object)
IL_0019: call object SmallVbLib.Class1::m(object,
object,
object)
IL_001e: call object [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::GetObjectValue(object)
IL_0023: stloc.0
IL_0024: ret
} // end of method Class1::Main

November 17, 2004 7:47 AM

TrackBack said:

Blog Posts I've
November 17, 2004 12:08 PM

Jeff Atwood said:

Yeah, the "VB.NOT" camp really f**cked us. Thanks guys. For nothing.

On the brighter side, VS.NET 2005 looks like it rectifies most of the issues, though.
November 17, 2004 3:30 PM

Daniel Moth said:

Try Catch IL
November 18, 2004 4:56 AM

Sahil Malik said:

Rather interesting - what did Carl think of this one?
December 8, 2004 7:38 AM

JMS said:

All will be good when C# catches up with VB; actually it is the MS C# VS IDE team that needs to catch up, isn't it!
September 3, 2008 8:42 PM

Leave a Comment

(required) 
(optional)
(required) 
Submit

About donxml

I’m an independent consultant, specializing in .Net solutions architecture, based out of New Jersey who also doubles as an evangelist for XML, Domain Driven Design, enterprise architecture and .Net. I do not work for Microsoft, the W3C or any other big company that you may know of (at least not yet). I’ve been an indie for over ten years, and although I’ve been tempted a couple times to take a job with companies like Microsoft, I’ve haven’t found something better than my current situation. I work mostly with the large pharmaceuticals that are based here in New Jersey, and usually find myself on long term contracts. Definitely not the prototypical indie consultant, but it lets me dedicate time to my non-income generating activities like the developer community stuff, plus financing open source projects like XPathmania and MVP-XML. If you would like to talk to me about doing some contract work, just contact me via the contact page. My rates vary widely, depending on lots of different variables, but mostly distance from Jersey, and type of work. Plus, I’ve been known to donate some of my code for various projects.
Powered by Community Server, by Telligent Systems