Code Focused

Life Without On Error Resume Next

The alternative to that simple error-handling combo is the Try...Catch, but it's not as simple as wrapping up your code with it.

Long before .NET arrived on the scene, the On Error statement in Visual Basic formed the foundation of that language's error management options. Through the judicious use of On Error GoTo statements and related error objects, you could craft error-handling code that was every bit as rugged and nearly as structured as the modern Try...Catch alternative. But when you didn't care anymore, there was this:

On Error Resume Next
DoSomethingUnsafe()
HereIsMoreDanger()

The On Error statement's Resume Next clause told the world, "Do what you want; ask me later if I care." It was a great way to ignore low-risk errors in your source code. But when misused, the statement could greatly complicate debugging and data issues. And, yet, there were times when it was the right tool. The cleanup of low-priority resources just before exiting an application is an example that comes to mind:

On Error Resume Next
resourceOne.Cleanup()
resourceTwo.Cleanup()
resourceThree.Cleanup()
End

When migrating such code to its structured alternative, the temptation is to wrap it all up in one large Try statement:

Try
  resourceOne.Cleanup()
  resourceTwo.Cleanup()
  resourceThree.Cleanup()
Catch
  ' ----- Ignore any error.
End Try
End

Unfortunately, this isn't the correct conversion, because any exception thrown by the cleanup of resourceOne will cause the code to completely skip the two remaining logic lines. A more accurate translation into modern .NET code would provide error handlers for each trouble-prone statement, as shown in Listing 1.

Listing 1: The Correct Way To Use Try…Catch
Try
  resourceOne.Cleanup()
Catch
  ' ----- Ignore any error.
End Try
Try
  resourceTwo.Cleanup()
Catch
  ' ----- Ignore any error.
End Try
Try
  resourceThree.Cleanup()
Catch
  ' ----- Ignore any error.
End Try
End

The code in Listing 1 is correct, and it provides task-specific opportunities to deal with any errors that do occur, even when moving from a procedure that formerly tossed caution to the wind.

Despite the validity of this code, you might wonder how the Visual Basic .NET compiler deals with On Error Resume Next. By building your Visual Basic project, and then extracting out the compiled result using the .NET Framework Intermediate Language (IL) Disassembler tool (ILDASM.EXE), you can see exactly what the compiler does. It's IL, so it's not pretty. But the Visual Basic code presented in Listing 2 shows generally what the compiler attempts to do.

Listing 2: What the Compiler Tries To Do, in Visual Basic
Dim position As Integer
Try
  position = 1
Statement01:
  position = 2
  resourceOne.Cleanup()
Statement02:
  position = 3
  resourceTwo.Cleanup()
Statement03:
  position = 4
  resourceThree.Cleanup()
Statement04:
  position = 0
  GoTo EndOfLogic

DealWithIt:
  Select Case position
    Case 0: GoTo EndOfLogic
    Case 1: GoTo Statement01
    Case 2: GoTo Statement02
    Case 3: GoTo Statement03
    Case 4: GoTo Statement04
  End Select
Catch
  GoTo DealWithIt
End Try
EndOfLogic:
End

The code depends heavily on the GoTo statement, using it to jump back into the action if an error ever does occur halfway through. It seems like a dramatic increase in code.

I'm not an expert in software benchmarking, but my guess is that the performance overhead inherent in repeatedly entering and exiting error handling blocks exceeds the extra time consumed by assigning the position variable over and over again. And if no exception is ever thrown, the entire DealWithIt block is passed over completely.

Which method should you use when replacing your unstructured error statements? It's difficult to answer without knowing the exact nature of your routine's logic. But if you have a secret desire to read through pages of assembly language-style code, using the output from the Visual Basic compiler isn't a bad place to start.

About the Author

Tim Patrick has spent more than thirty years as a software architect and developer. His two most recent books on .NET development -- Start-to-Finish Visual C# 2015, and Start-to-Finish Visual Basic 2015 -- are available from http://owanipress.com. He blogs regularly at http://wellreadman.com.

comments powered by Disqus

Featured

  • Compare New GitHub Copilot Free Plan for Visual Studio/VS Code to Paid Plans

    The free plan restricts the number of completions, chat requests and access to AI models, being suitable for occasional users and small projects.

  • Diving Deep into .NET MAUI

    Ever since someone figured out that fiddling bits results in source code, developers have sought one codebase for all types of apps on all platforms, with Microsoft's latest attempt to further that effort being .NET MAUI.

  • Copilot AI Boosts Abound in New VS Code v1.96

    Microsoft improved on its new "Copilot Edit" functionality in the latest release of Visual Studio Code, v1.96, its open-source based code editor that has become the most popular in the world according to many surveys.

  • AdaBoost Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the AdaBoost.R2 algorithm for regression problems (where the goal is to predict a single numeric value). The implementation follows the original source research paper closely, so you can use it as a guide for customization for specific scenarios.

  • Versioning and Documenting ASP.NET Core Services

    Building an API with ASP.NET Core is only half the job. If your API is going to live more than one release cycle, you're going to need to version it. If you have other people building clients for it, you're going to need to document it.

Subscribe on YouTube