VB Catch ... When: Why so special?

VB Catch ... When: Why so special?

Rate This
  • Comments 5

The VB Catch syntax has a unique feature: When.  It allows users to filter expressions based on something other than their type.  Any arbitrary code can enter a When block to decide whether or not to handle an Exception.

    Sub Sub1()
        Try
            DoSomeAction()
        Catch ex As Exception When Filter(ex)
            Stop
        End Try
    End Sub

Newsgroups often ask, "Why's this so special? I could effectively get the same behavior out of C# by doing the following:"

static void Sub1()
{
    try
    {
        DoSomeAction();
    }
    catch (Exception ex)
    {
        if (Filter(ex))
        {
            throw;
        }
        HandleException();
    }
}

This is true to an extent.  In both cases the code is handling an exception and making a decision, via calling Filter, as to whether or not to handle the exception.  The subtle difference is when the Filter method is called. 

In VB the When statement is actually implemented as an IL exception filter.  When an exception is thrown, exception filters are processed before the stack is unwound.  This means that if the Filter method created an error report that included the current stack trace, it would show the frame in which the exception occurred. 

For example, in the code above if DoSomeAction() threw and the stack was examined in the Filter expression, the following stack would show up.

image

Notice how the DoSomeAction method is clearly visible?  This is incredibly powerful for features like error reporting and investigation.  It also allows you to set powerful breakpoints where the exact state of the error can be examined and not just the post mortem. 

Alternatively, code executed in the C# block will occur after the stack is unwound.  As long as you're not in optimized code you can usually use the stack trace properties to get the source of the exception, but you won't be able to examine the live state of the error.

image

Leave a Comment
  • Please add 7 and 3 and type the answer here:
  • Post
  • There's also the convenience part of it. In C# catch-rethrow solution, with default VS settings, it won't break on the original throw down the stack (because it's caught upwards), but it will break on rethrow if the filter fails, because that one is uncaught. On VB, if the filter fails, there is quite literally no catch, and the debugger correctly breaks on the line that originally threw the exception.

  • Please deprecate this feature in VB.  Keep VB and C# consistent.  The minimal reduction in the number of lines of code is outweighed by the extra effort you need to understand/maintain the code.

  • Er... you want to deprecate an immensely useful VB feature just because C# doesn't have it? How about spending 5 minutes (you know, the amount it takes to type "Where" in MSDN Library index and glance at the first paragraph of the article that opens) to learn the language you end up coding in?

    If anything, I'd rather ask to have that feature in C#. And I'm really a C# programmer, not a VB one.

  • The real value of this is that when an exception is being filtered, nested finally blocks are not run first. If they run, they corrupt the program state or cause further problems, before you can examine the original one. That is what happens when you try to filter exceptions with catch/throw. It is vital to have exception filtering for this reason. C# is incomplete without it.

  • Yeah, deprecate the more evolved functionality...  My name says it all.

Page 1 of 1 (5 items)