简体   繁体   English

使用嵌套的“ try / finally”“ try / except”语句

[英]Use of nested “try/finally” “try/except” statements

I have seen this code posted here on StackOverflow: 我已经在StackOverflow上看到了以下代码:

with TDownloadURL.Create(nil) do
  try
    URL := 'myurltodownload.com';
    filename := 'locationtosaveto';
    try
      ExecuteTarget(nil);
    except
      result := false;
    end;
    if not FileExists(filename) then
      result := false;
  finally
    free;
  end;

Can't it be simplified to look like: 不能简化为:

 Result:= FALSE;               <--------- Compiler complains
 DeleteFile(Dest);
 dl:= TDownloadURL.Create(NIL);
 TRY
   dl.URL:= URL;
   dl.FileName:= Dest;
   dl.ExecuteTarget(NIL);           
   Result:= FileExists(Dest);
 FINALLY
   dl.Free;
 END;

The final Result:= ... will never be executed if something went wrong in 'ExecuteTarget' be cause the program will jump directly to 'finally'. 如果'ExecuteTarget'中出现问题,则最终Result:= ...将永远不会执行,因为该程序将直接跳转到'finally'。 Right? 对? So, the function will return FALSE. 因此,该函数将返回FALSE。 Am I doing something wrong? 难道我做错了什么?


PS: PS:

  1. I intend to use this code in a thread. 我打算在线程中使用此代码。
  2. I just put the function in Delphi and the compiler complaints about the first line: "Value assigned never used." 我只是将函数放在Delphi中,而编译器则抱怨第一行:“从未使用分配的值”。

The difference is that your second example passes exceptions back to the caller, while the original traps them and returns false. 不同之处在于您的第二个示例将异常传递回调用方,而原始示例将其捕获并返回false。 I'd characterise that style of coding as "I don't care why it failed, I only care whether it succeeded". 我将这种编码风格描述为“我不在乎它为什么失败,我只在乎它是否成功”。 Which can be reasonable in some cases (like trying to download an update). 在某些情况下(例如尝试下载更新),这可能是合理的。

So your code is very different from the original in that way - you are expecting the caller to handle exceptions that the original code does not. 因此,您的代码与原始代码有很大的不同-您期望调用方处理原始代码没有的异常。

Also, the compiler complaint is because there's no branch in your code - either if works and result is determined by the second assignment or you have an exception and Result is irrelevant. 另外,编译器的抱怨是因为您的代码中没有分支-无论是工作和结果是由第二个赋值确定的,还是您有异常且Result不相关。

Result := FALSE; //   <--------- Compiler complains
DeleteFile(Dest);
dl := TDownloadURL.Create(nil);
try
   dl.URL := URL;
   dl.FileName := Dest;
   dl.ExecuteTarget(nil);
   Result := FileExists(Dest);
finally
   dl.Free;
end;

In the original, if ExecuteTarget throws an exception, it will still test of filename exists. 原来,如果ExecuteTarget抛出异常,它将仍然测试文件名是否存在。

In yours, if ExecuteTarget throws an exception, result is always false. 在您的情况下,如果ExecuteTarget引发异常,则结果始终为false。

Also, unless you skipped a line, on the original, if ExecuteTarget succeeds and the file exists, result is never set. 另外,除非您跳过了一行,否则如果ExecuteTarget成功且文件存在,则在原始文件上永远不会设置result

The first version just eat the exception and never raise to upper callers, it treat exception as false return. 第一个版本只吃掉异常,而不会引发更高的调用者,它将异常视为错误返回。 For your simple version, exception will be thrown out. 对于您的简单版本,将抛出异常。

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

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