5

我有一些看起来像这样的代码:

foreach(var obj in collection)
{
   try
   {
      // WriteToFile returns the name of the written file
      string filename = WriteToFile(obj); 
      SendFileToExternalAPI(filename);
   }
   catch ( ArbitraryType1Exception e )
   {
      LogError(e);
      continue;
   }
   ...
   catch ( ArbitaryTypeNException e )
   {
      LogError(e);
      continue;
   }
   finally
   {
      try
      {
         File.Delete(filename);
      }
      catch (Exception e)
      {
         LogError(e);
      }
   }
}

目标是尝试为集合中的每个对象写出一个临时文件,尝试将该文件加载到需要文件名的外部 API 中,然后在完成后清理临时文件。如果在将文件写入磁盘或将其加载到外部 API 时发生错误,我只想记录错误并转到下一个对象;我不能问用户该怎么做。

当您在 catch 处理程序中有 continue 语句时,我有点不确定 finally 块的时间是如何工作的。无论 try 块中是否引发异常,此代码是否会(尝试)删除正确的文件?或者 catch 语句中的 continue 是否在 finally 块运行之前生效?

4

4 回答 4

16

将其视为带有可选捕获表达式的 try/finally 块。代码中的两个 continue 语句都会将执行堆栈从 catch 中弹出,这会将执行放在 finally 块中,然后再允许循环继续。任何时候有一个 try/finally 块,finally 都会被执行。

于 2012-06-26T03:41:30.890 回答
8

无论是否抛出异常,都会执行您的 finally 块。因此,您的 finally 块将始终被执行。

于 2012-06-26T03:33:34.560 回答
6

finally作为完成前的最后一步执行try。因此它会在正确的时间发生。为了更容易概念化,想想如果所有continue语句都被替换会发生什么return-finally仍然会执行。

于 2012-06-26T03:37:28.057 回答
6

来自C# 语言规范

8.9.2 continue 语句

...

continue 语句不能退出 finally 块(第 8.10 节)。当 continue 语句出现在 finally 块中时, continue 语句的目标必须在同一个 finally 块中;否则会发生编译时错误。

continue 语句执行如下:

· 如果 continue 语句退出一个或多个带有相关 finally 块的 try 块,则控制最初转移到最里面的 try 语句的 finally 块。当控制到达 finally 块的终点时,控制将转移到下一个封闭 try 语句的 finally 块。重复此过程,直到所有介入的 try 语句的 finally 块都已执行。

...

于 2012-06-26T03:41:26.477 回答