delphi - 为什么在明显的 "safe"代码中使用异常处理?

标签 delphi try-except

请有人解释一下,这段代码中什么会引发异常?

function CreateBibleNames: TStrings;
begin
  Result := TStringList.Create;
  try
    Result.Add('Adam');
    Result.Add('Eva');
    Result.Add('Kain');
    Result.Add('Abel');
  except
    Result.Free;
    raise;
  end;      
end;

自从我使用delphi以来,我可能使用过一次异常处理。我认为上面的代码是由熟练的程序员编写的,并且我不认为异常是多余的。但是,在这个概念中使用异常处理对我来说仍然是一个谜。这似乎是一个安全的代码(除了结束之外没有尝试)。我已经看过很多次类似的代码片段,这就是为什么尽管我的经验如此,但可能有充分的理由这样编写,但这并不能证明它是必要的。

此外,当出现故障时,我会收到异常描述......

谢谢

最佳答案

好吧,那段代码很奇怪,我同意,而且我完全理解为什么要这样写。但之所以这样写,是因为代码的前提是错误的。事实上,该结构看起来很奇怪,这应该是一种“代码味道”,并且应该告诉您某些事情可能没有以最佳方式完成。

首先,这就是为什么在 try... except block 中使用不寻常的构造。该函数创建一个 TStringList,但如果在填充过程中出现问题,那么创建的 TStringList 将在堆上“丢失”,并且会出现内存泄漏。因此,最初的程序员是防御性的,并确保如果发生异常,TStringList 将被释放,然后异常将再次引发。

现在这是“坏前提”部分。该函数返回 TStrings 的实例。这并不总是解决这个问题的最佳方法。返回这样的对象实例会引发一个问题“谁将处理我创建的这个东西?”。它造成了一种情况,在调用方,很容易忘记 TStrings 实例已被分配。

这里的“更好的实践”是让函数将 TStrings 作为参数,然后填充现有实例。这样,谁拥有实例(调用者)以及谁应该管理其生命周期就毫无疑问了。

因此,该函数成为一个过程,可能如下所示:

procedure CreateBibleNames(aStrings: TStrings);
begin
  if aStrings <> nil then
  begin
    aStrings .Add('Adam');
    aStrings .Add('Eva');
    aStrings .Add('Kain');
    aStrings .Add('Abel');
  end;      
end;

这并不是说每次返回对象实例都是一件坏事——例如,这是非常有用的工厂模式的唯一功能。但对于像这样的更“通用”的功能,上面是一种“更好”的做事方式。

关于delphi - 为什么在明显的 "safe"代码中使用异常处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1894983/

相关文章:

delphi - 错误地调用继承会造成什么损害?

python - 尝试除了不必要的步骤

arrays - Delphi XE3 -> 整数到字节数组

windows - 使用 Indy 组件发送电子邮件

windows - 使用 Delphi 查找特殊驱动器

python退出无限while循环并出现KeyboardInterrupt异常

python - 用 `try except` 尝试两个表达式

python - 在循环中捕获异常回溯,然后在脚本末尾引发错误

python - turtle.TurtleGraphicsError没有注册?

Delphi——将整数转换为类型指针?