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

时间:2012-08-10 12:23:54

标签: performance delphi 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;

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

3 个答案:

答案 0 :(得分:8)

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

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

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

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

答案 1 :(得分:4)

如果时间效率是您唯一的标准,那么第一个会更快,因为异常处理是CPU消耗。

FileExists()使用一个WinApi调用,因此它很快,但只检查文件是否存在。 如果文件存在但其格式错误或被其他线程阻止,则会出现未处理的异常。

答案 2 :(得分:0)

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

  1. 如果第一个文件确实存在,请加载它,否则加载第二个文件。如果第一个文件存在但无法加载,则显示错误。
  2. 如果无法加载第一个文件,则回退到第二个文件。
  3. 如果你想要1)的语义,你的第一个代码就可以了。

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

    1. 有竞争条件。如果在检查文件存在和加载文件之间删除图像,它将失败。
    2. 如果文件存在但无法加载,则会引发异常。如果文件没有有效图像,或者无法打开,则会发生这种情况。
    3. 第二个使用异常来处理常见情况,这是不好的。

      所以要实现我使用的第二个语义:

      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;
      

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

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

      您还应该考虑更具针对性的例外条款。毯子捕捉所有异常都是糟糕的风格。不幸的是,我找不到TPicture.LoadFromFile抛出异常的明确规范,所以我暂时留下一揽子条款。