6.4 Resuming Code

only for RuBoard

Sometimes you'll just want to keep on trucking after an error has occurred rather than handle it. Example 6-7 demonstrates an unstructured approach to ignoring errors. Normally this code would throw a DivideByZeroException , but here On Error Resume Next is used to prevent exceptions from propagating out of the method.

Example 6-7. On Error Resume Next
 'Throws System.DivideByZeroException   Public Class App   Public Shared Sub Main( )     On Error Resume Next     Dim x As Integer = 0     Dim y As Integer = 10 \ x     'Use x and y here   End Sub End Class 

Many of you know that ignoring errors like this is considered bad practice. Even so (or so you say), sometimes it needs to be done. A safer approach would be to turn off error handling specifically where you need to, and then turn it back on when you are done:

 Public Sub SomeMethod( )     On Error Goto errHandler  On Error Resume Next  '  Code that might trigger errors goes here   On Error Goto errHandler  Exit Sub errHandler:     'Handle errors here     End Sub 

There are several arguments against this approach. Handling (or not handling) errors in this way does not produce the most readable code. Program flow jumps all over the place. Also, if this technique is used in a method that contains even a small degree of complexity, debugging could turn into a nightmare.

On Error Resume Next results in inefficient code. It might be one line of code in VB, but you'd be amazed by the IL spaghetti that is generated by the compiler. Remember Example 6-7? It uses On Error Resume Next , declares two integers, and performs a division. Example 6-8 shows the IL produced by this example. We will not even attempt to discuss the listing for this "simple" example. The listing is provided only for its magnitude. Just scan it and remember it the next time you are tempted to turn off error handling in your code.

Example 6-8. Disassembly of Resume Next
 //  Microsoft (R) .NET Framework IL Disassembler.  Version 1.0.3705.0  //  Copyright (C) Microsoft Corporation 1998-2001. All rights reserved.     .assembly extern mscorlib {   .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )  // .z\V.4..   .ver 1:0:3300:0 } .assembly extern Microsoft.VisualBasic {   .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )  // .?_....:   .ver 7:0:3300:0 } .assembly extern System {   .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )  // .z\V.4..   .ver 1:0:3300:0 } .assembly extern System.Data {   .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )  // .z\V.4..   .ver 1:0:3300:0 } .assembly extern System.Xml {   .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )  // .z\V.4..   .ver 1:0:3300:0 } .assembly extern System.Web {   .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )  // .?_....:   .ver 1:0:3300:0 } .assembly temp3 {   .custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::     .ctor(string) = ( 01 00 00 00 00 )    // --- The following custom attribute is added automatically, do not uncomment -------   //  .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(bool,    //                                                                                bool)   //                                                              = ( 01 00 01 01 00 00 )   .custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::     .ctor(string) = ( 01 00 24 38 31 36 37 39 30 37 42 2D 30 35 35 38  // ..67907B-0558 2D 34 38 33 30 2D 41 36 34 30 2D 35 44 31 46 46   // -4830-A640-5D1FF 44 42 43 41 34 43 34 00 00 )                      // DBCA4C4..   .custom instance void [mscorlib]System.CLSCompliantAttribute::.ctor(bool) = ( 01 00 01                                                                                 00 00 )   .custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::     .ctor(string) = ( 01 00 00 00 00 )    .custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::     .ctor(string) = ( 01 00 00 00 00 )    .custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::     .ctor(string) = ( 01 00 00 00 00 )    .custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::     .ctor(string) = ( 01 00 00 00 00 )    .custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string)  = ( 01 00 00 00 00 )    .hash algorithm 0x00008004   .ver 1:0:830:30783 } .module temp3.exe // MVID: {667EE811-3A5C-4236-8B2C-5703ED42C24C} .imagebase 0x11000000 .subsystem 0x00000003 .file alignment 512 .corflags 0x00000001 // Image base: 0x02df0000 // // ============== CLASS STRUCTURE DECLARATION ================== // .namespace temp3 {   .class public auto ansi App          extends [mscorlib]System.Object   {   } // end of class App     } // end of namespace temp3         // =============================================================         // =============== GLOBAL FIELDS AND METHODS ===================         // =============================================================         // =============== CLASS MEMBERS DECLARATION =================== //   note that class flags, 'extends' and 'implements' clauses //          are provided here for information only     .namespace temp3 {   .class public auto ansi App          extends [mscorlib]System.Object   {     .method public specialname rtspecialname              instance void  .ctor( ) cil managed     {       // Code size       9 (0x9)       .maxstack  8       IL_0000:  ldarg.0       IL_0001:  call       instance void [mscorlib]System.Object::.ctor( )       IL_0006:  nop       IL_0007:  nop       IL_0008:  ret     } // end of method App::.ctor         .method public static void  Main( ) cil managed     {       .entrypoint       .custom instance void [mscorlib]System.STAThreadAttribute::.ctor( ) =                                                                   ( 01 00 00 00 )        // Code size       134 (0x86)       .maxstack  2       .locals init ([0] int32 x,                [1] int32 y,                [2] int32 _Vb_t_CurrentStatement,                [3] class [mscorlib]System.Exception _Vb_t_Exception,                [4] int32 _Vb_t_Resume,                [5] int32 _Vb_t_OnError)       IL_0000:  nop       IL_0001:  call       void [Microsoft.VisualBasic]Microsoft.VisualBasic.                            CompilerServices.ProjectData::ClearProjectError( )       IL_0006:  ldc.i4.1       IL_0007:  stloc.s    _Vb_t_OnError       IL_0009:  ldc.i4.1       IL_000a:  stloc.2       IL_000b:  ldc.i4.0       IL_000c:  stloc.0       IL_000d:  ldc.i4.2       IL_000e:  stloc.2       IL_000f:  ldc.i4.s   10       IL_0011:  ldloc.0       IL_0012:  div       IL_0013:  stloc.1       IL_0014:  leave.s    IL_007b           IL_0016:  ldloc.s    _Vb_t_Resume       IL_0018:  ldc.i4.1       IL_0019:  add       IL_001a:  ldc.i4.0       IL_001b:  stloc.s    _Vb_t_Resume       IL_001d:  switch     (                              IL_0001,                             IL_0009,                             IL_000d,                             IL_0014)       IL_0032:  leave.s    IL_0079           IL_0034:  isinst     [mscorlib]System.Exception       IL_0039:  brtrue.s   IL_003d           IL_003b:  br.s       IL_0048           IL_003d:  ldloc.s    _Vb_t_OnError       IL_003f:  brfalse.s  IL_0048           IL_0041:  ldloc.s    _Vb_t_Resume       IL_0043:  brtrue.s   IL_0048           IL_0045:  ldc.i4.1       IL_0046:  br.s       IL_004b           IL_0048:  ldc.i4.0       IL_0049:  br.s       IL_004b           IL_004b:  endfilter       IL_004d:  castclass  [mscorlib]System.Exception       IL_0052:  dup       IL_0053:  call       void [Microsoft.VisualBasic]Microsoft.VisualBasic.            CompilerServices.ProjectData::SetProjectError(class [mscorlib]System.Exception)       IL_0058:  stloc.3       IL_0059:  ldloc.s    _Vb_t_Resume       IL_005b:  brfalse.s  IL_005f           IL_005d:  leave.s    IL_0079           IL_005f:  ldloc.2       IL_0060:  stloc.s    _Vb_t_Resume       IL_0062:  ldloc.s    _Vb_t_OnError       IL_0064:  switch     (                              IL_0073,                             IL_0075)       IL_0071:  leave.s    IL_0077           IL_0073:  leave.s    IL_0077            IL_0075:  leave.s    IL_0016           IL_0077:  rethrow       IL_0079:  ldloc.3       .try IL_0001 to IL_0034 filter IL_0034 handler IL_004d to IL_0079       IL_007a:  throw           IL_007b:  nop       IL_007c:  ldloc.s    _Vb_t_Resume       IL_007e:  brfalse.s  IL_0085           IL_0080:  call       void [Microsoft.VisualBasic]Microsoft.VisualBasic.                            CompilerServices.ProjectData::ClearProjectError( )       IL_0085:  ret     } // end of method App::Main       } // end of class App         // =============================================================     } // end of namespace temp3     //*********** DISASSEMBLY COMPLETE *********************** // WARNING: Created Win32 resource file C:\Programming VB.NET Objects\book - version 2\ Example6-7.res 

The best way to write code that needs to resume is to use structured error handling in place of outdated , unstructured approaches. Anywhere you need to resume from an error, use nested Try blocks instead. These blocks result in more code, but the code is more readable, easier to debug, and flows nicely from top to bottom:

 Try         'Resume #1         Try         'Resume if this code fails     Catch e As Exception         'Handle error     Finally         'Clean up     End Try         'Resume #2     Try         'Resume if this code fails     Catch e As Exception         'Handle error     Finally         'Clean up     End Try     Catch e As Exception    'Handle error Finally    'Clean up End Try 
only for RuBoard


Object-Oriented Programming with Visual Basic. Net
Object-Oriented Programming with Visual Basic .NET
ISBN: 0596001460
EAN: 2147483647
Year: 2001
Pages: 112
Authors: J.P. Hamilton

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net