How should I re-raise a Delphi exception after logging it?

前端 未结 8 1306
攒了一身酷
攒了一身酷 2021-01-01 10:40

Do you know a way to trap, log, and re-raise exception in Delphi code? A simple example:

procedure TForm3.Button1Click(Sender: TObject);
begin
  try
    rais         


        
8条回答
  •  清酒与你
    2021-01-01 11:20

    You could acquire the exception object before calling your handler and keep the handler itself one liner. However, you still have a lot of "Try/Except/Do/End" burden.

    Procedure MyExceptionHandler(AException: Exception);
    Begin
      Log(AException); // assuming it accepts an exception
      ShowMessage(AException.Message);
      raise AException; // the ref count will be leveled if you always raise it
    End;
    
    Procedure TForm3.Button1Click(Sender: TObject);
    Begin
      Try
        Foo;
      Except On E:Exception Do
        MyExceptionHandler(Exception(AcquireExceptionObject));
      End;
    End;
    

    However, if what you only want to do is to get rid of repetitive error handling code in event handlers, you could try this:

    Procedure TForm3.ShowException(AProc : TProc);
    Begin
      Try
        AProc;
      Except On E:Exception Do Begin
        Log(E);
        ShowMessage(E.Message);
      End; End;
    End;
    

    Reducing your event handler code to this:

    Procedure TForm3.Button1Click(Sender: TObject);
    Begin
      ShowException(Procedure Begin // anon method
        Foo; // if this call raises an exception, it will be handled by ShowException's handler
      End);
    End;
    

    You can also make it work for functions, using parametrized functions:

    Function TForm3.ShowException(AFunc : TFunc) : T;
    Begin
      Try
        Result := AFunc;
      Except On E:Exception Do Begin
        Log(E);
        ShowMessage(E.Message);
      End; End;
    End;
    

    And making ShowException return a value (acting as a passthru):

    Procedure TForm3.Button1Click(Sender: TObject);
    Var
      V : Integer;
    Begin
      V := ShowException(Function : Integer Begin // anon method
        Result := Foo; // if this call raises an exception, it will be handled by ShowException's handler
      End);
    End;
    

    Or even making the anon procedure touch directly the outer scope variable(s):

    Procedure TForm3.Button1Click(Sender: TObject);
    Var
      V : Integer;
    Begin
      ShowException(Procedure Begin // anon method
        V := Foo; // if this call raises an exception, it will be handled by ShowException's handler
      End);
    End;
    

    There are some limitations on the interaction of variables from inside the body of the anonymous function and the ones defined in the outer scope, but for simple cases like these, you will be more than fine.

提交回复
热议问题