【问题标题】:In delphi 7, is `try ... except raise; end;` meaningful at all?在 delphi 7 中,是 `try ... except raise;结束;`有意义吗?
【发布时间】:2010-10-22 18:01:04
【问题描述】:

在我维护的一些 Delphi 7 代码中,我注意到以下很多实例:

with ADOQuery1 do begin
  // .. fill out sql.text, etc
  try
    execSQL;
  except
    raise;
  end;
end;

在我看来,这些 try 块可以被删除,因为它们什么都不做。但是,我对可能的微妙副作用保持警惕..

谁能想到这些块实际上可以做任何没有它们就不会发生的事情?

【问题讨论】:

标签: delphi exception try-catch delphi-7


【解决方案1】:

在这种情况下,raise 操作没有任何效果,应该被删除,因为它只是重新引发异常块刚刚捕获的异常。 raise 通常用于在没有适当的错误处理可用时将控制转移到块的末尾。下面我们处理自定义异常,但任何其他异常都应该在其他地方处理。

try
  someOperation;
except
  on e: ECustomException do
    SomeCustomHandelr;
  else
     begin
       // the raise is only useful to rethrow the exception to an encompasing 
       // handler.  In this case after I have called my logger code. as Rob
       // mentioned this can be omitted if you arent handling anything because
       // the compiler will simply jump you to the next block if there is no
       // else.
       LogUnexpectedException('some operation failed',e);
       raise;
     end;
end;

请注意,没有“加注”的类似外观形式确实具有吃/隐藏任何异常的副作用。非常不道德的开发人员的实践,他们希望在竞争中获得职位。

with ADOQuery1 do begin  
  // .. fill out sql.text, etc  
  try    
    execSQL; 
  except
    // no handler so this just eats any "errors"    
  end;

【讨论】:

  • Mike,你的第一个例子不需要“raise”。任何不是 ECustomException 类型的异常都会自动传播到下一个处理程序。只需省略整个“其他”部分。
  • 你是对的。它在那里是出于习惯。唯一需要 else raise 的时候是如果你有一些其他的代码你想执行然后需要它。在我的晚年生锈。
【解决方案2】:

删除上面代码sn-p中的except代码将没有任何区别。您可以(而且我相信您应该,因为它会降低可读性)删除它。

【讨论】:

  • 放弃这样的代码的另一个好理由:在调试时,您不想在出现异常时单步执行所有这些。
【解决方案3】:

好的,这里真的有两个问题。

首先,它有意义的:如果execSQL 抛出异常,它会被try 块捕获并转发到except。然后通过 raise 将其转发到下一个更高的块。

第二,它有用吗?可能不是。这几乎可以肯定是以下三件事之一的结果:

  1. 头发尖的人写了一个编码标准,规定“所有可以抛出异常的操作都必须在 try 块中。”
  2. 有人打算回来将execSQL 声明产生的异常转化为其他更有意义的异常。
  3. 新人不知道他们所写的内容与让外部环境担心异常是同构的,因此认为他们必须转发它。

【讨论】:

  • 让我担心的是我知道这段代码是谁写的,我认为1-3在这里不适用。除了可能 3.. 嗯。
  • 哦,他走了,所以我不能问他。
  • 这个人以前用Java写过代码吗?也许那时他认为必须捕获异常并且没有尝试其他方法。
  • 在 Java 中,并非所有异常都必须被捕获,只有“检查异常”。
  • @mjustin,我想我们都同意这是一个对异常的使用有误解的人。
【解决方案4】:

我可能回答的有点快,看最后...
这样,对应用没用
期间!

现在在“为什么”方面。如果在其他地方/曾经/将要/在其他地方/在 raise 之前插入了某种日志记录代码,则可能是为了标准化异常处理:

  try
    execSQL;
  except
    // Log Exception..
    on E: Exception do
    begin
      LogTrace(Format('%s: Exception Message[%s]',[methodname, E.Message]));
      raise;
    end;
  end;

或者对于清理代码:

  try
    execSQL;
  except
    //some FreeAndNil..
    raise;
  end;

更新:在 1 种情况下,我会看到一些类似的用途......
...能够在raise 行上放置一个断点,以便有机会查看该代码块的上下文中发生了什么。

【讨论】:

  • 第二个完全不习惯,可以用 finally 代替。像这样的东西确实会降低代码库的可读性,所以这也是修复它的一个原因。
  • 用 Connection.Rollback 替换 FreeAndNil
  • 完全是 Blorgbeard,只有在出现问题时才需要进行任何类型的内务管理,然后您继续进行异常冒泡
  • 是的,你是对的。从评论中我看不出 FreeAndNil() 是有条件的,但现在我明白了。
  • 将此作为放置断点的机会似乎有点愚蠢,因为引发的异常无论如何都会将您发送到调试器。
【解决方案5】:

此代码除了允许原始程序员在“引发”上放置断点并在源中更接近其可能原因之外查看异常。从这个意义上说,它是一种完全合理的调试技术。

【讨论】:

    【解决方案6】:

    实际上,我应该将此作为对 François 答案的评论发布,但我不知道是否可以在此处插入格式化代码 :( 所以我将其发布为答案。

    2mghie:

    第二个是完全不习惯的,一个会用 finally 代替。

    不,“finally”将始终清理对象。 “例外” - 仅在例外情况下。考虑函数的情况,它创建、填充和返回一个对象:

    function CreateObj: TSomeObj;
    begin
      Result := TSomeObj.Create;
      try
        ... // do something with Result: load data, fill props, etc.
      except
        FreeAndNil(Result); // oops: bad things happened. Free object to avoid leak.
        raise;
      end;
    end;
    

    如果您将“finally”放在那里 - 函数将始终返回 nil。如果您完全省略“try”块 - 如果“...”中出现异常,则会出现资源泄漏。

    附:当然,你可以使用“finally”并检查ExceptObj,但是……那不是很丑吗?

    【讨论】:

    • 我同意,请参阅我对弗朗索瓦回答的评论。
    【解决方案7】:

    标题包含一个相当广泛的问题,而它的解释给出了一个更具体的例子。因此,我对这个问题的回答是如何从示例中进行的,无疑可以为这里已经说过的内容添加任何有用的东西。

    但是,也许Blorgbeard 确实想知道它是否根本try ... except raise; end 有意义。在 Delphi 7 中,如果我没记错的话,Exit 会触发try-finally 块的finally 部分(就好像它是某种异常一样)。有人可能会认为这种行为不适合他们的任务,使用有问题的结构是一种很好的解决方法。

    只是在那里使用单个raise; 仍然很奇怪,但是我们应该讨论有用性而不是意义,正如查理巧妙地观察到的那样。

    【讨论】:

    • Finally 块在 所有 情况下执行,无论是否异常,所以不可能。
    【解决方案8】:

    这段代码除了重新引发一个异常之外什么都不做,如果没有这个 try except 块,就会引发一个异常。您可以安全地删除它。

    【讨论】:

      猜你喜欢
      • 2018-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-09
      • 1970-01-01
      • 2018-01-23
      • 2014-05-04
      • 2019-06-26
      相关资源
      最近更新 更多