嵌套异常的正确方法是什么? - 使用Delphi [英] What is the correct way to nest exceptions? - Using Delphi

查看:142
本文介绍了嵌套异常的正确方法是什么? - 使用Delphi的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有三个(或多个)程序,其中一些程序相互调用,如下所示,任何一个都可能失败。



如果任何一个失败,我希望主程序立即记录失败并终止程序。



在Delphi中使用什么正确的语法将异常传回每个前面的过程调用?



更好的是,如果有人可以帮助我获得主程序的Try / except块,以确定哪个位失败!



三个程序的样本伪代码和主程序可能如下所示。



(我认为我理解与加注有关的原则,但是想要一些帮助实际的语法和什么代码我应该使用)

  /////////// //////////////////////// 
过程DoProcA
begin
try
begin
{stuff}; //可能会
结束的东西;
除了
在E上:异常do
begin
LogError('A'中的错误);
end // on E
end; // try

////////////////////// ////////////

过程DoProcB
begin
try
begin
做ProcC; //另一个可能失败的proc
{other stuff}
end;
除了
对于E:异常do
begin
LogError('B'中的错误);
end // on E
end; // try

////////////////////// ////////////

过程DoProcC
开始
尝试
开始
{做东西} //甚至更多的可能会失败
结束;
除了
对于E:异常do
begin
LogError('C'中的错误);
end // on E
end; // try

////////////////////// //////////////

//主程序
begin
try
DoProcA;
DoProcB;
{其他东西}
除了
{这里我想要能够像
那样做,如果A,B或C失败然后
开始
LogError(A,B或C中的某个地方出现故障);
application.terminate;
end;}
end; //尝试
结束。


解决方案

各功能重新加注记录后捕获的异常,例如:

 过程DoProcA; 
begin
try
{stuff}; //可能会下降
的东西,除了
在E:Exception do
begin
LogError('A in');
加注//< - -
end;
结束
结束

过程DoProcB;
begin
try
DoProcC; //另一个可能失败的进程
{other stuff}
除了
在E:Exception do
begin
LogError('B'中的错误);
加注//< - -
end;
结束
结束

过程DoProcC;
begin
try
{Do stuff} //甚至更多的东西可能会失败
除了
在E:Exception do
begin
LogError ('C'中的错误);
加注//< - -
end;
结束
结束

begin
try
DoProcA;
DoProcB;
{other stuff}
除了
对于E:异常do
begin
LogError('A,B或C'中的某处失败);
//Application.Terminate; //这不是有用的,除非Application.Run首先被调用
end;
结束
结束。

如果您希望主程序识别WHICH功能失败,则需要将该信息传递给异常链接,例如:

 键入
MyException = class(Exception)
public
WhereFunc:串;
构造函数CreateWithFunc(const AWhichFunc,AMessage:String);
结束

构造函数MyException.CreateWithFunc(const AWhichFunc,AMessage:String);
begin
继承Create(AMessage);
WhereFunc:= AWhichFunc;
结束

过程DoProcA;
begin
try
{stuff}; //可能会下降
的东西,除了
在E:Exception do
begin
raise MyException.CreateWithFunc('DoProcA',E.Message); //< - -
end;
结束
结束

过程DoProcB;
begin
try
DoProcC; //另一个可能失败的进程
{其他东西}
除了
在E:MyException do
begin
raise; //< - -
end;
on E:Exception do
begin
raise MyException.CreateWithFunc('DoProcB',E.Message); //< - -
end;
结束
结束

过程DoProcC;
开始
尝试
{做东西} //更多的东西可能会失败
除了
在E:异常do
开始
加MyException.CreateWithFunc('DoProcC',E.Message); //< - -
end;
结束
结束

begin
try
DoProcA;
DoProcB;
{other stuff}
除了
在E:MyException do
begin
LogError('Failure in'+ E.WhichFunc +':'+ E.Message) ;
结束
在E:Exception do
begin
LogError('Failure at other else:'+ E.Message);
结束
结束
结束。

或:

 code> type 
MyException = class(Exception)
public
WhereFunc:String;
构造函数CreateWithFunc(const AWhichFunc,AMessage:String);
结束

构造函数MyException.CreateWithFunc(const AWhichFunc,AMessage:String);
begin
继承Create(AMessage);
WhereFunc:= AWhichFunc;
结束

过程DoProcA;
begin
try
{stuff}; //可能会下降
的东西,除了
在E:Exception do
begin
raise MyException.CreateWithFunc('DoProcA',E.Message); //< - -
end;
结束
结束

过程DoProcB;
begin
try
DoProcC; //另一个可能失败的进程
{other stuff}
除了
在E:Exception do
begin
Exception.RaiseOuterException(MyException.CreateWithFunc('DoProcB' E.Message)); //< - -
end;
结束
结束

过程DoProcC;
开始
尝试
{做东西} //更多的东西可能会失败
除了
在E:异常do
开始
加MyException.CreateWithFunc('DoProcC',E.Message); //< - -
end;
结束
结束

var
例外:异常;
begin
try
DoProcA;
DoProcB;
{other stuff}
除了
在E:Exception do
begin
Ex:= E;
重复
如果Ex是MyException然后
LogError('失败在'+ MyException(Ex).WhichFunc +':'+ Ex.Message)
else
LogError (其他地方失败:+ Ex.Message);
Ex:= Ex.InnerException;
,直到Ex = nil;
结束
结束
结束。


Assume I have three (or more) procedures, some of which call each other, as shown below, any one of which can fail.

If any one of them do fail I want the 'main' program to immediately log the failure and terminate the program.

What is the correct syntax to use in Delphi to 'pass back' an exception to each preceeding procedure call?

Even better if someone can help me to get the main program's Try/except block to identify which bit failed!

Sample pseudo code of the three procedures and the main program might look like below.

(I think I understand the principle, something to do with 'raise', but would like some help with the actual syntax and what code I should use)

//////////////////////////////////////
Procedure DoProcA
begin
try
   begin
   {stuff};  //stuff that might fall
   end;
except
 on E : Exception do 
     begin 
     LogError ('error in A'); 
     end  //on E
end;//try

 //////////////////////////////////////

Procedure DoProcB
begin
try
  begin 
  Do ProcC;  //another proc that might fail
  {other stuff}
  end;
except
 on E : Exception do
     begin
     LogError ('error in B');
     end  //on E
end;//try

 //////////////////////////////////////

Procedure DoProcC
begin
try
  begin 
  {Do stuff}  //even more stuf fthat might fail
  end;
except
 on E : Exception do
     begin
     LogError ('error in C');
     end  //on E
end;//try

 //////////////////////////////////////

 //Main programo
 begin 
 try
    DoProcA;
    DoProcB;
    {other stuff}
 except
   {here I want to be able to do something like
    if failure of A, B or C then
       begin      
       LogError ('Failure somewhere in A, B or C');
       application.terminate;
       end;}
 end; //try
 end.

解决方案

Have each function re-raise the caught exception after logging it, eg:

Procedure DoProcA;
begin
  try
    {stuff};  //stuff that might fall
  except
    on E : Exception do 
    begin 
      LogError ('error in A'); 
      raise; // <-- here
    end;
  end;
end;

Procedure DoProcB;
begin
  try
    DoProcC;  //another proc that might fail
    {other stuff}
  except
    on E : Exception do
    begin
      LogError ('error in B');
      raise; // <-- here
    end;
  end;
end;

Procedure DoProcC;
begin
  try
    {Do stuff}  //even more stuff that might fail
  except
    on E : Exception do
    begin
      LogError ('error in C');
      raise; // <-- here
    end;
  end;
end;

begin 
  try
    DoProcA;
    DoProcB;
    {other stuff}
  except
    on E: Exception do
    begin
      LogError ('Failure somewhere in A, B or C');
      //Application.Terminate; // this is not useful unless Application.Run is called first
    end;
  end;
end.

If you want the main procedure to identify WHICH function failed, you need to pass that information down the exception chain, eg:

type
  MyException = class(Exception)
  public
    WhichFunc: String;
    constructor CreateWithFunc(const AWhichFunc, AMessage: String);
  end;

constructor MyException.CreateWithFunc(const AWhichFunc, AMessage: String);
begin
  inherited Create(AMessage);
  WhichFunc := AWhichFunc;
end;

Procedure DoProcA;
begin
  try
    {stuff};  //stuff that might fall
  except
    on E : Exception do 
    begin 
      raise MyException.CreateWithFunc('DoProcA', E.Message); // <-- here
    end;
  end;
end;

Procedure DoProcB;
begin
  try
    DoProcC;  //another proc that might fail
    {other stuff}
  except
    on E : MyException do
    begin
      raise; // <-- here
    end;
    on E : Exception do
    begin
      raise MyException.CreateWithFunc('DoProcB', E.Message); // <-- here
    end;
  end;
end;

Procedure DoProcC;
begin
  try
    {Do stuff}  //even more stuff that might fail
  except
    on E : Exception do
    begin
      raise MyException.CreateWithFunc('DoProcC', E.Message); // <-- here
    end;
  end;
end;

begin 
  try
    DoProcA;
    DoProcB;
    {other stuff}
  except
    on E: MyException do
    begin
      LogError ('Failure in ' + E.WhichFunc + ': ' + E.Message);
    end;
    on E: Exception do
    begin
      LogError ('Failure somewhere else: ' + E.Message);
    end;
  end;
end.

Or:

type
  MyException = class(Exception)
  public
    WhichFunc: String;
    constructor CreateWithFunc(const AWhichFunc, AMessage: String);
  end;

constructor MyException.CreateWithFunc(const AWhichFunc, AMessage: String);
begin
  inherited Create(AMessage);
  WhichFunc := AWhichFunc;
end;

Procedure DoProcA;
begin
  try
    {stuff};  //stuff that might fall
  except
    on E : Exception do 
    begin 
      raise MyException.CreateWithFunc('DoProcA', E.Message); // <-- here
    end;
  end;
end;

Procedure DoProcB;
begin
  try
    DoProcC;  //another proc that might fail
    {other stuff}
  except
    on E : Exception do
    begin
      Exception.RaiseOuterException(MyException.CreateWithFunc('DoProcB', E.Message)); // <-- here
    end;
  end;
end;

Procedure DoProcC;
begin
  try
    {Do stuff}  //even more stuff that might fail
  except
    on E : Exception do
    begin
      raise MyException.CreateWithFunc('DoProcC', E.Message); // <-- here
    end;
  end;
end;

var
  Ex: Exception;
begin 
  try
    DoProcA;
    DoProcB;
    {other stuff}
  except
    on E: Exception do
    begin
      Ex := E;
      repeat
        if Ex is MyException then
          LogError ('Failure in ' + MyException(Ex).WhichFunc + ': ' + Ex.Message)
        else
          LogError ('Failure somewhere else: ' + Ex.Message);
        Ex := Ex.InnerException;
      until Ex = nil;
    end;
  end;
end.

这篇关于嵌套异常的正确方法是什么? - 使用Delphi的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆