在delphi 7中,是`try ...除了raise;结束;“有意义吗?

时间:2009-04-30 02:12:52

标签: delphi exception try-catch delphi-7

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

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

在我看来,这些尝试块可以删除,因为它们什么都不做。但是,我对可能存在的微妙副作用持谨慎态度。

任何人都可以想到这些块实际上可以做任何没有它们的事情吗?

8 个答案:

答案 0 :(得分:10)

在这种情况下,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;

答案 1 :(得分:6)

删除上面代码段中的except代码没有任何区别。您可以(并且我相信您因为它会降低可读性)将其删除。

答案 2 :(得分:2)

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

首先, 是有意义的:如果execSQL抛出异常,它会被try块捕获并转发给except。然后它被加注转发到下一个更高的区块。

其次,有用吗?可能不是。这几乎肯定是三件事之一的结果:

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

答案 3 :(得分:2)

我可能回答得有点快,最后看到......
就像它一样,它对应用程序来说是无用的 期!

现在关于“为什么”的一面。可能是标准化异常处理,如果/是/将/在其他地方/在加注之前插入某种日志代码:

  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;

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

答案 4 :(得分:2)

除了允许原始程序员在“Raise”上放置断点并在源中看到更接近其可能原因的异常之外,此代码不执行任何操作。从这个意义上讲,这是一种非常合理的调试技术。

答案 5 :(得分:1)

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

2mghie:

  
    
      

第二个完全是单一的,最后会用到。

    
  

不,“终于”将始终清理对象。 “除了” - 仅限于例外情况。考虑函数的情况,它创建,填充并返回一个对象:

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”块 - 如果在“...”中出现异常,将会有资源泄漏。

P.S。当然,你可以使用“finally”并检查ExceptObj,但是......不是那么难看吗?

答案 6 :(得分:0)

标题包含相当广泛的问题,而其解释给出了一个更具体的例子。所以,我回答这个例子的问题,可以肯定地增加了对这里所说的内容有用的东西。

但是,也许 Blorgbeard确实想知道try ... except raise; end有意义是否有意义。在Delphi 7中,如果我正确地重新收集,Exit将触发finally块的try-finally部分(就好像它是某种例外)。有人可能认为这种行为不适合他们的任务,使用有问题的结构是一种解决方法。

只有在那里使用单个raise;仍然很奇怪,但我们应该谈论有用性而不是有意义,因为查理已经整齐地观察到的。

答案 7 :(得分:0)

此代码除了重新引发异常之外什么都不做,除了块之外没有这个尝试。你可以安全地删除它。