10

我被推荐使用第二个,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;
4

3 回答 3

8

忘记效率。代码可读性更重要。过早的优化是万恶之源。

第一个是明确的意图。每个人都可以很容易地弄清楚发生了什么。

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

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

于 2012-08-10T13:17:05.577 回答
4

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

FileExists() 使用一个 WinApi 调用,因此速度很快,但它仅检查文件是否存在。如果文件存在但格式错误或被其他线程阻塞,您将获得未处理的异常。

于 2012-08-10T13:07:10.637 回答
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;

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

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

您还应该考虑更有针对性的例外条款。捕捉所有异常的毯子是不好的风格。不幸的是,我找不到一个明确的规范,哪些异常是由 引发的TPicture.LoadFromFile,所以我现在将留在一揽子条款中。

于 2012-08-10T12:34:04.940 回答