After a series of long IM sessions with Cory explaining my earlier post on VB.NET and Exceptions, he decided to post his thoughts on the matter. And Paul Vick weighed in through comments...
> Our assumption is that the first thing that people will do is specialize the exception, anyway...
The problem is that most of the VB code that I have worked with (I am a consultant and have worked on about 15 different .NET applications within the past couple years) is that developers don't specialize the exception, they swallow the error. I have spoken on Exceptions at a number of user groups, and at each one I hear "well why would you go through the trouble of creating a new Exception type when you can just catch Exception?"
Which is why I said that VB.NET propogates improper SEH.
The average programmer does not care about the implications of SEH or learning past a basic syntax level. Many are just familiar enough with SEH to port some of their old “On Error Goto Hell“ code (a co-worker of mine routinely used that error label in his VB6 code, always cracked me up). I have spoken with seasoned developers who also questioned why you would write specialized exceptions and not simply always catch System.Exception and throw ApplicationException.
And I don't claim that there is a possible buffer overrun exploit in unmanaged code, that was Charles Torre's post. The part that I was referring to in Brumme's post regarded the StackOverflowException.
Methods should not catch Exception because StackOverflowException, OutOfMemoryException, and ExecutionEngineException could happen at any time without relation to the current method. Although the docs state that EngineExecutionException should never happen, a version of the Oracle ODP.NET driver did cause this to happen in ASP.NET apps. Much more common is the OutOfMemoryException type: suppressing this type of exception is A Very Bad Thing, especially when the system generated text contains “There was not enough memory to continue the execution of the program.“
If you have a method that reasonably expects a StackOverflowException, then by all means catch it and process it. But if your method is not prepared to do anything with a StackOverflowException (or more importantly, it came out of the blue in a method that adds two numbers), then it should bubble to the caller. The caller, then, is responsible for doing something to respond to unforseen behavior. Whether that is logged, displayed, bubbled to the AppDomain.UnhandledExceptionEventHandler, or is bubbled to the default handler is up to the caller.
My problem with autocompleting "Catch ex As Exception" is that many developers perceive this as the correct way to code, period. An app I recently worked on sparked a long debate about this because there were no typed exceptions, everything was typed as Exception. When posed with the OutOfMemoryException case, the client responded “That's never going to happen.“ Turned out that they were simultaneously having problems with their app suddenly quitting... and nary a Finally statement to be found to clean up resources. And it is not just one app, but nearly all of the apps that I have worked with involved at least 2 developers not familiar with SEH in .NET.
Autocompleting a Finally statement would be more appropriate, because the developer has to explicitly type the Exception derivative that they could reasonably handle within a method, akin to the C# using statement. But if VB.NET gets a using statement in v 2.0, then great: I just hope that it gets used.
Update:
Cowboy (Gregory A. Beamer) IM'd me with some additional reinforcement for not catching System.Exception, but the explicit type:
From the Exception Management in .NET book:
"You should only catch exceptions when you need to specifically perform any of the following actions:
Gather information for logging
Add any relevant information to the exception
Execute cleanup code
Attempt to recover
If a particular method does not need to perform any of these actions, it should not catch the exception; rather, it should allow it to propagate back up the call stack. This keeps your code clean and explicit as you only catch the exceptions that need to be handled within the scope of a particular method and allow all others to continue to propagate."