Try without Catch



  • Hi,

    this is a VB.Net question.

    If I use the following bit of code, would that cause any unforeseen problems with the order in which commands are executed?

    try
    ....
    finally
    ....
    end try

    Note that I do not want to catch any exceptions (to preserve their original metadata) but I do want to execute the finally block (ie. close database connections etc).

    In what order will the commands be executed?

    Drak



  • Betreft: Try without Catch

    try

      Will_Execute

      Will_Execute_Too

      Crash_and_Raise_Exception

      Will_NOT_be_Executed

    finally

      Will_Execute_Three

    end try



    However, keep in mind that the finally part can raise an exception too,
    which would be unhandled in that case. In general it's better to use
    try-except instead and if you don't want to handle the exception, just
    don't do anything in the except block. Thus:



    try


      Will_Execute



      Will_Execute_Too



      Crash_and_Raise_Exception



      Will_NOT_be_Executed


    except

    end try

    Will_Execute_Three



    Above code would do the same as the first block. At least in Delphi. VB might be a bit quirky at this... [;)]


  • ♿ (Parody)

    When code in the Try block throws an exception, the exception is raised, and then the Finally block executes. Let's say you have ..

    Try
      myCmd.ExecuteNonQuery()
      myCmd2.ExecuteNonQuery()
      myCmd3.ExecuteNonQuery()
    Finally
      myConn.Close()
    End Try

    If myCmd2 fails, myCmd3 will never execute. myConn.Close() will always* execute.

    * There are certain rare cases where code in a finally block is not executed. Very, very rare.



  • Thanks for the replies!

    I will use try...finally...end try [:D]

    Drak



  • Note that a catch block will be executed _before_ your finally block. But it is guaranteed to be executed. From VB.NET spec, 8.11.1.1:

    A Finally block is always executed when execution leaves any part of the Try statement. No explicit action is required to execute the Finally block; when execution leaves the Try statement, the system will automatically execute the Finally block and then transfer execution to its intended destination. The Finally block is executed regardless of how execution leaves the Try statement: through the end of the Try block, through the end of a Catch block, through an Exit Try statement, through a GoTo statement, or by not handling a thrown exception.

     



  • It's true that the catch block would be executed first, but the point of the question was what would happen if I didn't include a catch block, but a level higher there would be one. Then my Finally goes off first, and the Catch goes off second because it is a level higher.

    Drak



  • Betreft: Re: Try without Catch

    Actually, a try-finally construction will ignore the exception and
    continue as if the exception is handled. The exception won't go off
    after the Finally, unless another exception is raised in or after the
    Finally...



    At least, that's the case in Delphi.



  • In the follwing code (vb.net):

    <FONT color=#0000ff size=2>

    Try
       </FONT><FONT color=#0000ff size=2>Try
          </FONT><FONT color=#0000ff size=2>Dim</FONT><FONT size=2> objhash </FONT><FONT color=#0000ff size=2>As</FONT><FONT size=2> Hashtable
          objhash("a") = </FONT><FONT color=#0000ff size=2>Nothing
       </FONT><FONT color=#0000ff size=2>Finally
          </FONT><FONT size=2>MsgBox("!")
       </FONT><FONT color=#0000ff size=2>End</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Try
    </FONT><FONT color=#0000ff size=2>Catch</FONT><FONT size=2> ex </FONT><FONT color=#0000ff size=2>As</FONT><FONT size=2> Exception
       MsgBox(ex.Message)
    </FONT><FONT color=#0000ff size=2>End</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>Try</FONT>

    <FONT color=#0000ff><FONT color=#000000>The output is a messagebox saying '!' followed by a messagebox saying that 'Object reference not set to an instance of an object', so it is handling the exception in the higher-level catch.</FONT></FONT>

    <FONT color=#0000ff size=2><FONT color=#000000 size=3>Drak</FONT>

    </FONT>


  • That's not how it works in Delphi.



    In a try-except construct, the exception is destroyed at the end of the
    except section. If you want it to propagate forward, you need to
    re-raise the exception.



    In a try-finally construct, the exception is automatically re-raised after the finally block.



    Take a look at the "Try...finally statements" and "Try...except statements" topics in the Delphi help.



  • Betreft: Re: Betreft: Re: Try without Catch

    From the Delphi help files...



    If an exception is raised but not
    handled in the finally clause, that exception is propagated out of the
    try...finally statement, and any exception already raised in the try
    clause is lost. The finally clause should therefore handle all locally
    raised exceptions, so as not to disturb propagation of other exceptions.



    So what does that mean, exactly? Well, I started to experiment. I
    created a new Delphi application with a new button and added this
    OnClick code:


    procedure TForm2.Button1Click( Sender: TObject );
    begin
      try
        try
          raise Exception.Create( 'Oops!' );
        finally Button1.Caption := FormatDateTime( 'HH:NN:SS.ZZZ', Now );
        end;
      except on E: Exception do Caption := E.Message + '/' + FormatDateTime( 'HH:NN:SS.ZZZ', Now );
      end;
    end;

    And indeed, Delphi executed both the Finally part as the Except part. Thus you're right. If the exception isn't handled then it will just be raised again after the Finally part, unless the Finally part itself creates a new exception.
    And now I know why my dad always advised me to only use try-except constructs. Simply because you always want to handle exceptions.


  • Using a Try with out a catch will not cause any problems and the code will execute as expected ( the Try code will run, and then the Finally code will run).  I have seen this done when the code uses non-managed resources and we want to make sure that we free those resources before we exit the process.  I am 99% sure that the error will bubble up after the Finally but you should check into that further.



  • Erm, if you wanted to handle the exception at a higher level,can VB do this?

    (Python stz)

    try:

       foo()

    except:

       raise

    finally:

       bob()

     



  • @Cyresse said:

    Erm, if you wanted to handle the exception at a higher level,can VB do this?

    (Python stz)

    try:

       foo()

    except:

       raise

    finally:

       bob()

     

    Yep, you can throw a new exception in the catch.

    Try

       TestSub()

    Catch

       Throw New (What ever exception you want.)

    Finally

       Do something

    End Try

     



  • One edit to the above code.



    Try

    ...Code that may throw exception...

    Catch ex as Exception

        throw    <--- push the caught exception up.

    Finally

    ...Always Executed Code Here...

    End Try



    It will not only push the error up it will execute the finally. 
    If you throw a new exception, you loose what really happened.



  • But what you are stating does exactly the same as leaving out the catch completely.

    I guess it would even compile to the same code [;)]

    Drak



  • @Cyresse said:

    Erm, if you wanted to handle the exception at a higher level,can VB do this?

    (Python stz)

    try:

       foo()

    except:

       raise

    finally:

       bob()

     

    You cannot use both except and finally in a Python exception-handling structure.

    You may use either try/except/else or try/finally (the finally will basically catch and re-raise any catched exception)



  • @masklinn said:

    @Cyresse said:

    Erm, if you wanted to handle the exception at a higher level,can VB do this?

    (Python stz)

    try:

       foo()

    except:

       raise

    finally:

       bob()

     

    You cannot use both except and finally in a Python exception-handling structure.

    You may use either try/except/else or try/finally (the finally will basically catch and re-raise any catched exception)



    So the else: in Python does the same as finally {} in other languages?

    Why have two syntaxes for a single construct?


  • @dhromed said:



    So the else: in Python does the same as finally {} in other languages?



    Why have two syntaxes for a single construct?


    They aren't the same thing.  The else part of a try/except/else
    construct will be executed only if an exception is not raised.



  • An interesting scenario:


    public static void main(String[] args) {

        try {

           foo();

        } catch (Exception e) {

           System.out.println(e.getMessage());

        }

    }


    public void foo() throws Exception {

        try {

           bar();

        } finally {

           baz();

        }

    }


    public void bar() throws Exception {

        throw new Exception("bar");

    }


    public void baz() throws Exception {

        throw new Exception("baz");

    }


    What gets printed when this is run?


    The answer is "baz" - the exception thrown by bar is apparently completely discarded!



  • @endergt said:

    The answer is "baz" - the exception thrown by bar is apparently completely discarded!




    First of all: Your code doesn compile. (can you say "static"?)



    Second: If you don't want exceptions in finally to hide uncaught exceptions, why don't you tell Java?



    <font size="2">    public static void foo() throws Exception {

            try {

                bar();

            } finally {

                try {

                    baz();

                } catch (Throwable t) {

                    // don't hide uncaught exceptions

                }

            }

        }

    </font>

    Or even better (but more to code):



    <font size="2">    public static void foo() throws Exception {

            boolean uncaughtExceptionOccurred = false;

            try {

                bar();

            } catch (Exception e) {

                uncaughtExceptionOccurred = true;

                throw e;

            } finally {

                try {

                    baz();

                } catch (Exception e) {

                    // don't hide uncaught exceptions

                    if (!uncaughtExceptionOccurred) {

                        throw e;

                    }

                }

            }

        }



    </font>I don't understand why so many people expect a computer to read
    minds. If you don't tell it what you want it to do, then don't wonder
    if it doesn't do it the way you want it to.



    cu



  • That's what I get for trying to simplify the test code. What I actually wrote and ran was structured differently.



    I don't expect the computer to read my mind... I'd just never come
    across this situation before and was wondering how Java would handle it.



  • @endergt said:

    That's what I get for trying to simplify the test
    code. What I actually wrote and ran was structured differently.



    I don't expect the computer to read my mind... I'd just never come
    across this situation before and was wondering how Java would handle it.




    Then sorry for my rant. I probably was upset from some other nonsense I spotted these days on de.comp.lang.java .



  • @Katja Bergman said:

    try

      Will_Execute

      Will_Execute_Too

      Crash_and_Raise_Exception

      Will_NOT_be_Executed

    finally

      Will_Execute_Three

    end try



    However, keep in mind that the finally part can raise an exception too,
    which would be unhandled in that case. In general it's better to use
    try-except instead and if you don't want to handle the exception, just
    don't do anything in the except block. Thus:



    try


      Will_Execute



      Will_Execute_Too



      Crash_and_Raise_Exception



      Will_NOT_be_Executed


    except

    end try

    Will_Execute_Three



    Above code would do the same as the first block. At least in Delphi. VB might be a bit quirky at this... [;)]




    try

      Will_Execute
      Will_Execute_Too
      Return_from_Function
      Will_NOT_be_Executed

    except

    end try

    Will_NOT_Execute_Either



    will behave differently, though. If it's important that the code is
    always executed, "finally" is the better choice. As for your argument
    that this can mean a "lost" exception - I don't know much about Delphi,
    but it would be quite braindead if it didn't allow try-except within a
    "finally"-block. This corresponds to the C++ rule that destructors
    should never throw (rsp. catch everything they throw).



Log in to reply