简体   繁体   English

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

[英]In delphi 7, is `try … except raise; end;` meaningful at all?

In some Delphi 7 code I am maintaining, I've noticed a lot of instances of the following: 在我维护的一些Delphi 7代码中,我注意到以下很多实例:

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

It seems to me that these try blocks could be removed, since they do nothing. 在我看来,这些尝试块可以被删除,因为它们什么都不做。 However, I am wary of possible subtle side-effects.. 但是,我对可能出现的微妙副作用持谨慎态度。

Can anyone think of any instances in which these blocks could actually do anything that wouldn't happen without them there? 任何人都可以想到这些块实际上可以做任何没有它们的情况下会发生的事情吗?

In this context, the raise operation has no effect and should be removed becuase its simply re-raising the exception that the exception block just caught. 在这种情况下,raise操作没有任何效果,应该删除它,因为它只是重新引发异常块刚刚捕获的异常。 raise is typically used to transfer control to the end of the block when no appropriate error handling is available. raise通常用于在没有适当的错误处理时将控制转移到块的末尾。 In the following we handle the custom exception, but any other exception should be handled elsewhere. 在下面我们处理自定义异常,但任何其他异常应该在别处处理。

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;

Be careful that there is similar looking form without the "raise" that DOES have the side effect of eating/hiding any exceptions. 小心有没有“提高”的类似外观形式,它具有吃/隐藏任何例外的副作用。 practicies by very unscrupulous developers who have hopefully moved on to positions with the competition. 非常肆无忌惮的开发人员的实践,他们希望能够在竞争中占据一席之地。

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

Removing the except code in above code snippet will make no difference. 删除上面代码段中的except代码将没有任何区别。 You can (and I believe you should since it is reducing the readability) remove it. 您可以(我相信您应该因为它降低了可读性)将其删除。

Okay, really two questions here. 好的,这里真的有两个问题。

First, it is meaningful: if execSQL throws an exception, it's caught by the try block and forwarded to the except. 首先,它有意义的:如果execSQL抛出异常,它会被try块捕获并转发到except。 Then it's forwarded on by the raise to the next higher block. 然后它被加注转发到下一个更高的块。

Second, is it useful ? 第二,它有用吗? Probably not. 可能不是。 It almost certainly is the result of one of three things: 它几乎肯定是三件事之一的结果:

  1. Someone with pointy hair wrote a coding standard that said "all operations that can throw an exception must be in a try block." 有尖头发的人写了一个编码标准,说“所有可以抛出异常的操作都必须在try块中”。
  2. Someone meant to come back and turn the exceptions made by the execSQL statment into some other, more meaningful, exception. 有人打算回来并将execSQL语句中的异常转换为其他更有意义的异常。
  3. Someone new wasn't aware that what they'd written was isomorphic to letting the uter environment worry about the exception, and so thought they must forward it. 有些新人并不知道他们所写的内容是同形的,让外部环境担心异常,所以他们认为必须转发它。

I may have answered a bit fast, see at the end... 我可能回答得有点快,最后看到......
Like it is, it is useless for the application . 就像它一样,它对应用程序来说是无用的
Period! 期!

Now on the "why" side. 现在关于“为什么”的一面。 It may be to standardize the exceptions handling if there /was/will be/is in other places/ some kind of logging code inserted before the raise: 可能是标准化异常处理,如果/是/将/在其他地方/在加注之前插入某种日志代码:

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

or for Cleanup code: 或者用于清理代码:

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

Update : There would be 1 case where I would see some use just like it is... 更新 :有一种情况我会看到一些使用就像它...
... to be able to put a Breakpoint on the raise line, to get a chance to see what's going on in the context on that block of code. ...能够在raise线上放置一个断点,以便有机会看到该代码块上下文中发生了什么。

This code does nothing, other than to allow the original programmer to place a breakpoint on the 'Raise' and to see the exception closer in the source to its possible cause. 除了允许原始程序员在'Raise'上放置断点并在源中看到更接近其可能原因的异常之外,此代码不执行任何操作。 In that sense it a perfectly reasonable debugging technique. 从这个意义上说,这是一种非常合理的调试技

Actually, I should posted this as comment to François's answers, but I don't know is it possible to insert formatted code there :( So I'm posting this as answer. 实际上,我应该将此作为对François的答案的评论发布,但我不知道是否可以在那里插入格式化的代码:(所以我将其作为答案发布。

2mghie: 2mghie:

The second one is completely unidiomatic, one would use finally instead. 第二个是完全单一的,最后会用到。

No, "finally" will cleanup object always. 不,“终于”将永远清理对象。 "Except" - only on exception. “除了” - 仅限于例外情况。 Consider the case of function, which creates, fills and return an object: 考虑函数的情况,它创建,填充和返回一个对象:

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;

If you put "finally" there - function will return nil always. 如果你把“finally”放在那里 - 函数将始终返回nil。 If you omit "try" block at all - there will be resources leak in case of exception in "...". 如果省略“try”块 - 在“...”中出现异常时会有资源泄漏。

PS Of course, you can use "finally" and check ExceptObj, but... isn't that ugly? PS当然,你可以使用“finally”并检查ExceptObj,但是......不是那么难看吗?

The title contains quite a broad question, while its explanation gives a more specific example. 标题包含相当广泛的问题,而其解释给出了一个更具体的例子。 So, my answering to the question as how it proceeds from the example, can doubtly add anything useful to what has already been said here. 所以,我回答这个例子的问题,可以肯定地增加了对这里已经说过的内容有用的东西。

But, maybe Blorgbeard indeed wants to know whether it is at all meaningful to try ... except raise; end 但是, 也许 Blorgbeard确实想知道它是否在所有有意义的try ... except raise; end try ... except raise; end . try ... except raise; end In Delphi 7, if I recollect correctly, Exit would trigger the finally part of a try-finally block (as if it were some sort of exception). 在Delphi 7中,如果我正确地重新收集, Exit将触发try-finally块的finally部分(就好像它是某种异常)。 Someone might consider such behaviour inappropriate for their task, and using the construction in question is quite a workaround. 有人可能认为这种行为不适合他们的任务,并且使用相关结构是一种解决方法。

Only it would still be strange to use a single raise; 只使用一次raise;仍然是奇怪的raise; there, but then we should have talked about usefulness rather than meaningfulness , as Charlie has neatly observed. 在那里,但我们应该谈论有用性而不是有意义 ,正如查理巧妙地观察到的那样。

This code does nothing except re-raising an exception that will allready be raised without this try except block. 除了重新引发一个异常,除了块之外没有这个尝试,这个代码什么都不做。 You can safely remove it. 你可以安全地删除它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM