Delphi中try...except...finally的意义是什么?

6
我知道这听起来像是一个老掉牙的问题,但我在互联网上搜索了很久,仍然不明白一件事。我知道try-finally将在停止错误之前运行最终代码(或者在没有引发异常时不会停止),而try-except将在引发异常时运行except代码。但我仍然不明白try-finally语句中try-except的意义。我会写一个例子
我通常做的是这样的:
a:=x.Create;
try 
  a.DoRiskyStuff;
except
  ShowMessage('Error!');
end;
a.free;

我从未使用过finally子句,因为我总是处理错误,并且我从来没有理解过使用它们嵌套在一起的意义。那么我的解决方案有什么问题?为什么在示例中通常使用这样的代码:

a:=x.Create;
try
  try
    a.DoRiskyStuff;
  except
    ShowMessage('Error!');
  end;
finally
  a.free;
end;

有什么区别?为什么有些人要在try-except之后使用finally子句来做所有的清理工作呢?

非常感谢您的任何回答!

编辑:我改变了创建行,所以有些人可能会批评我;)


3
他们使用 - 是谁?Delphi没有try-except-finally结构。 - MBo
1
请先深入了解一下,您所询问的代码片段是虚假的,并且无法编译。您是否是指在try...finally语句中嵌套try...except语句? - Free Consulting
1
第一个是错误的,因为它在实例上调用了构造函数。你真正的问题是试图早期处理异常。不要这样做。让异常继续传递。让知道如何处理它们的东西来处理它们。 - David Heffernan
2
finally块不一定是为了异常。它们还可以通过exit、break或continue离开块时触发(但不包括goto;这将无法编译)。 - Rob Kennedy
2
不,当讨论异常时,我的意思是您应该删除异常处理并让顶级异常处理程序来处理它。然后,您应该使用finally来管理生命周期。 - David Heffernan
显示剩余10条评论
1个回答

6

这两个结构有两个主要的区别,一个是技术上的,另一个是语义上的。

技术上的区别

从技术上讲,它们的区别在于,finally 块将始终被执行,即使没有异常,而 except 块只有在出现异常时才会被执行。

即使在 try-finally 块中使用 Exit 提前退出函数,finally 块也会被执行。

此外,finally 块不会吞噬异常,而 except 块通常会吞噬异常,只有当异常类型不匹配你在 on ... do 中指定的异常类型,或者手动重新引发异常时,它才能逃离该块。

语义上的区别

except 块用于处理异常,而 finally 块则不是。 finally 块用于包含应该被执行的代码,而不管是否出现异常,即主要用于保护资源。因此,你应该这样做:

X := TY.Create;
try
  // Code that may raise an exception.
finally
  X.Free; // Free resource, even if there was an exception.
          // Exception is NOT handled.
end;

并且:

try
  // Code that may raise an exception.
except
  // Handle the kind of exceptions you can handle.
end;

请注意,在使用finally进行资源保护时,并不限于内存和Free。您可以恢复/撤销/关闭任何需要恢复/撤销/关闭的内容,例如关闭已打开的文件、关闭已打开的连接、关闭已启动的硬件,将鼠标指针恢复到其先前的形式等等。
因此,您也可以在以下代码中使用它:
Cursor := crMultiDrag;
try
  // Code that may raise exception.
finally
  Cursor := crDefault;
end;

1
谢谢您的回答。我理解这些区别。但我不理解为什么它们会像在try-finally中使用try-except一样一起使用。很抱歉,我之前在问题中写错了,但我已经纠正过来了。 - jano152
我刚试了一下,编译得挺好的。这正是我所想的-尽管我认为将它们放在一起没有什么用,但当我在寻找try-finally的用法时,我发现有人会像这样使用它们。 - jano152
1
不,我在发布问题时没有考虑过这个问题,现在也不认为有必要。 - jano152
尝试...除非...最后...结束; 在Delphi中编写它不会编译。只有try try ... except ... end finally ... end;才可以。所以我想知道你是如何编译你的代码的。而且你真的不理解finally。如果你理解了,你会经常使用finally,而far less often使用except。 - Rudy Velthuis
1
你写道:“我只在存在风险的代码中使用try-except,比如涉及用户输入或文件写入的情况。其他情况基本上都是可预测的。” 这表明你使用try/except来保护资源,而不是try/finally。 - David Heffernan
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接