在加载之前检查文件是否存在更快,或者在不存在时捕获异常?

Bog*_*BBA 10 delphi performance if-statement try-except

我被推荐使用第二个,try-except变体,但我也想知道其他人的想法:下面两个(如果有的话)哪个程序更节省时间?

procedure LoadImage(img: TImage; filename: string);
begin
  if fileexists(filename) then
    img.Picture.Loadfromfile(filename)
  else
    img.Picture.Loadfromfile('default.jpg')
end;
Run Code Online (Sandbox Code Playgroud)

要么

procedure LoadImage(img: TImage; filename: string);
begin
  try
    img.Picture.Loadfromfile(filename)
  except
    img.Picture.Loadfromfile('default.jpg')
  end
end;
Run Code Online (Sandbox Code Playgroud)

Nic*_*ges 8

忘记效率.代码可读性方式更重要.过早优化是各种邪恶的根源.

第一个是明确的意图.每个人都可以轻松搞清楚到底是什么.

第二个让我停下来走"什么......?"

你永远不希望你的代码引起第二反应.

  • 你还没有回答这个问题.抱怨这个问题首先被问到是可以的,但是如果投诉不会伴随着答案,那么无论它有多么好,它都应该在评论中. (5认同)
  • 清除错误的代码永远不应该优先于不太清晰的正确代码.不,我不是说第二个是正确的. (2认同)

Cod*_*aos 0

您的问题的一个问题是您没有指定所需的语义。有两种可能的解释,哪种解决方案更好取决于该选择。我认为无法加载后备是一个致命错误。

  1. 如果第一个文件确实存在,则加载它,否则加载第二个文件。如果第一个文件存在,但无法加载,则显示错误。
  2. 如果第一个文件无法加载,则回退到第二个文件。

如果您想要 1) 的语义,您的第一个代码就可以了。

如果您想要 2) 的语义,则两者都不好。第一个代码没有这些语义,因为:

  1. 它有一个竞争条件。如果在检查文件是否存在和加载文件之间图像被删除,它将失败。
  2. 如果文件存在,但无法加载,则会抛出异常。如果文件不是有效图像或无法打开,则可能会发生这种情况。

第二种使用常见情况的异常,这是很糟糕的。

因此,为了实现第二个语义,我将使用:

procedure LoadImage(img: TImage; filename: string);
var success:boolean;
begin
  success := false;
  if FileExists(filename)
    then try
      img.Picture.LoadFromFile(filename);
      success := true;
    except
    end
  if not success
    then img.Picture.LoadFromFile('default.jpg');
end;
Run Code Online (Sandbox Code Playgroud)

在打开之前检查是否存在会使错误情况更快,但成功情况会更慢。所以哪一个更快取决于你的使用情况。

就我个人而言,我会使用第三个变体而不是第二个变体,即使图像只是偶尔丢失,因为我相信正常运行的应用程序不应该抛出异常。如果基准测试显示性能问题很明显,我只会关心性能问题。

您还应该考虑更有针对性的例外条款。笼统地捕捉所有异常是不好的风格。不幸的是,我找不到明确的规范来抛出哪些异常TPicture.LoadFromFile,所以我现在将保留在毯子条款中。

  • 永远永远永远永远永远永远永远永远永远将 except 子句留空。曾经! (9认同)
  • 现在,您首先从文件名加载,然后放弃它以加载default.jpg。缺少“其他”。 (2认同)
  • 我不会使用空的 except 子句,那是自找麻烦。 (2认同)
  • @NickHodges该代码执行的操作与仍然包含“try LoadFromFile(filename);”的操作完全相同。除了 LoadFromFile('default.jpg'); 结束;`。我同意 ` except end` 不好,但是 ` except LoadFromFile('default.jpg'); end`同样糟糕。 (2认同)
  • 我建议使用更具体的异常过滤,因此它只捕获 IO 相关的异常。但我在文档中找不到说明该方法可能抛出哪些异常的声明。你有好的来源吗?但将其留空并不比原始问题中所做的更糟糕。 (2认同)