记录后如何重新引发Delphi异常?

Nik*_*rov 25 delphi exception-handling

你知道在Delphi代码中捕获,记录和重新引发异常的方法吗?一个简单的例子:

procedure TForm3.Button1Click(Sender: TObject);
begin
  try
    raise Exception.Create('Bum');
  except
    on E: Exception do
    begin
      MyHandleException(E);
    end;
  end;
end;

procedure TForm3.MyHandleException(AException: Exception);
begin
  ShowMessage(AException.Message);
  LogThis(AException.Message);  
  // raise AException; - this will access violate
end;
Run Code Online (Sandbox Code Playgroud)

所以我需要在except块中重新提升它,但我想知道是否有更好的方法来编写我自己的方法来处理和(在特定条件下)重新引发异常.

And*_*and 31

如果您只想在特定条件下重新引发异常,请写入

procedure TForm3.Button1Click(Sender: TObject);
begin
  try
    raise Exception.Create('Bum');
  except
    on E: Exception do
    begin
      if MyHandleException(E) then
        raise;
    end;
  end;
end;

function TForm3.MyHandleException(AException: Exception): boolean;
begin
  ShowMessage(AException.Message);
  result := true/false;
end;
Run Code Online (Sandbox Code Playgroud)


Wes*_*Wes 10

继Craig Young的帖子之后,我成功地使用了以下代码.您可以使用带有ExceptAddr函数的"at"标识符来保留原始异常位置.原始异常类类型和信息也会保留.

procedure MyHandleException(AMethod: string);
var
  e: Exception;
begin
  e := Exception(AcquireExceptionObject);
  e.Message := e.Message + ' raised in ' + AMethod; 
  raise e at ExceptAddr;
end;

try
  ...
except
  MyHandleException('MyMethod');
end;
Run Code Online (Sandbox Code Playgroud)


Dis*_*ned 6

以下方法可行,但由于以下两个原因当然不理想:

  • 异常是从调用堆栈中的不同位置引发的.
  • 您没有获得异常的精确副本 - 尤其是那些添加属性的类.即你必须明确地复制你需要的属性.
  • 由于需要进行类型检查,复制自定义属性可能会变得混乱.

.

procedure TForm3.MyHandleException(AException: Exception);
begin
  ShowMessage(AException.Message);
  LogThis(AException.Message);  
  raise ExceptClass(AException.ClassType).Create(AException.Message);
end;
Run Code Online (Sandbox Code Playgroud)

好处是您保留原始异常类和消息(以及您希望复制的任何其他属性).

理想情况下,你想要调用System._RaiseAgain,但唉,这是一个'编译器 - 魔术'例程,只能被调用raise;.