FURTHER CLARIFICATION: How to correctly write Try..Finally..Except statements?

后端 未结 3 1199
猫巷女王i
猫巷女王i 2020-12-18 16:24

RE: How to correctly write Try..Finally..Except statements?

I\'m still confused by the OP\'s original question. Specifically, the last line of the procedure (outside

相关标签:
3条回答
  • 2020-12-18 16:36

    In Delphi, the finally block doesn't really handle the exception that occured in the try block. It only guarantees that the code in the finally block will always be executed, whether an exception occured or not in the try block. If an exception really happened in there, it won't get caught. And when an exception didn't get caught, you know what happened to the code below it.

    To catch the exception that might be occured, use the try...except... block instead. You can combine these two construct to do those two action: (1) guarantee the execution some piece of code, and (2) catch the exceptions which might occured. The common usage is like this:

    try
      try
        // do something that might cause an exception.
      finally
        // do something that must be executed WHATEVER happened.
      end;
    except
      // do something ONLY IF an exception has occured.
    end;
    

    So, you should change your code and move the Screen.Cursor := crDefault; inside the finally block. In addition, add the try...except... block to surround the try...finally... block. Like this:

    procedure TForm1.Button1Click(Sender: TObject);
    var
      Obj: TSomeObject;
    begin
      Screen.Cursor := crHourGlass;
      Obj := TSomeObject.Create;
      try
        try
          // do something.
        finally
          Obj.Free;
          Screen.Cursor := crDefault;
        end;
      except
        ShowMessage('An error has occured!');
      end;
    end;
    

    Or, if you are not sure that the code Obj := TSomeObject.Create; is safe enough, you should add the second try...finally... block to surround it, like this:

    procedure TForm1.Button1Click(Sender: TObject);
    var
      Obj: TSomeObject;
    begin
      Screen.Cursor := crHourGlass;
      try
        try
          Obj := TSomeObject.Create;
          try
            // do something.
          finally
            Obj.Free;
          end;
        finally
          Screen.Cursor := crDefault;
        end;
      except
        ShowMessage('An error has occured!');
      end;
    end;
    

    There, hope it helps :)

    0 讨论(0)
  • 2020-12-18 16:39

    You don't actually catch the exception. In this case, upon exception, the "finally" block of code will execute, and then the exception will unwind the stack.

    0 讨论(0)
  • 2020-12-18 16:40

    The code you posted seems to work fine, because you're able to handle all possibilities. Try changing it somewhat though, so that there's an exception raised your code doesn't handle:

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      try
        try
          raise Exception.Create('42');
        except
          on E: EDivByZero do
            ShowMessage('DivByZero');
        end;
      finally
        ShowMessage('Finally');
      end;
      ShowMessage('Got here');
    end;
    

    Run this, and you'll see Finally, then the exception for 42, but no Got here message. This is because the exception took you out of the current block, the stack is unwound, and the code from the end of the finally to the end of the procedure never executes.

    Move the final ShowMessage call from where it is to inside the finally and run again.

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      try
        try
          raise Exception.Create('42');
        except
          on E: EDivByZero do
            ShowMessage('DivByZero');
        end;
      finally
        ShowMessage('Finally');
        ShowMessage('Got here');
      end;
      ShowMessage('Will never get here');
    end;
    

    You'll now see both calls to ShowMessage in the finally block, one after the other, but not the one after the finally block's end;. Code inside the finally block is guaranteed to execute, while code beyond it may or may not.

    To make it even more clear, the presence of the try..except block can be removed:

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      try
        raise Exception.Create('42');
      finally
        ShowMessage('Finally');
        ShowMessage('Got here');
      end;
      ShowMessage('Will never get here');
    end;
    

    The entire purpose of the try..finally block is to ensure that code inside the finally section will execute before the procedure ends.

    0 讨论(0)
提交回复
热议问题