gpt4 book ai didi

delphi - 在某些情况下使用 Abort 来改进/简化代码

转载 作者:行者123 更新时间:2023-12-03 15:19:05 28 4
gpt4 key购买 nike

前几天我进行了讨论:https://stackoverflow.com/a/42156860/937125我不太明白为什么在这种情况下 Abort 比调用 Exit 更好。我倾向于不在我的代码流中使用它。我认为这是一种不好的做法,并且不利于代码流程。但@David 在评论中的陈述让我想知道我是否遗漏了一些东西:

Without a silent exception, how would you abort an operation when deep down the call stack. For instance how would you abort a file copy operation with a 10 deep call stack? Isn't that exactly what exceptions are designed for? Sure you can code it without exceptions but it is much more verbose and error prone.

我无法想象这样的情况。有人可以给我一个此类代码/场景的示例,并让我相信上述情况下的Abort确实是一件好事,并且“更加冗长且容易出错”。 (3-4深的调用栈就足以说明)

最佳答案

说明我的观点的最简单的场景如下:

procedure MethodA;
begin
MethodB;
MethodC;
end;

procedure MethodB;
begin
// ... do stuff
end;

procedure MethodC;
begin
// ... do stuff
end;

这样就很好了。现在假设 MethodB 要求用户进行一些输入,如果用户按下 Cancel 按钮,则不应执行进一步的工作。你可以这样实现:

procedure MethodA;
begin
if MethodB then
MethodC;
end;

function MethodB: Boolean;
begin
Result := MessageDlg(...)=mrOK;
if not Result then
exit;
// ... do stuff
end;

procedure MethodC;
begin
// ... do stuff
end;

这很好用,但想象一下在现实世界的代码中,有更深的嵌套。 MethodB 返回的 bool 值可能需要向上传递很多级别。这会变得很麻烦。

或者考虑如果 MethodB 需要向其调用者返回一个值会发生什么。在这种情况下,原始代码可能如下所示:

procedure MethodA;
begin
MethodC(MethodB);
end;

function MethodB: string;
begin
Result := ...;
end;

procedure MethodC(Value: string);
begin
// ... do stuff with Value
end;

现在再考虑一下如果用户有机会取消会发生什么。我们如何从 MethodB 中同时返回 bool 值和字符串?使用输出参数作为返回值之一?使用像记录这样的复合结构来包装这两个值。后者显然涉及大量样板,所以让我们探索前者。

procedure MethodA;
var
Value: string;
begin
if MethodB(Value) then
MethodC(Value);
end;

function MethodB(out Value: string): Boolean;
begin
Result := MessageDlg(...)=mrOK;
if not Result then
exit;
Value := ...;
end;

procedure MethodC(Value: string);
begin
// ... do stuff with Value
end;

当然,您可以做到这一点,但这开始看起来像是异常旨在简化的代码类型。此时,让我们考虑是否存在通过调用 Abort 引发的静默异常 EAbort,该异常不会导致顶级异常显示消息处理程序。最后一点就是沉默的含义。

现在代码变成:

procedure MethodA;
begin
MethodC(MethodB);
end;

function MethodB: string;
begin
if MessageDlg(...)<>mrOK then
Abort;
Result := ...;
end;

procedure MethodC(Value: string);
begin
// ... do stuff with Value
end;

优点是MethodA不需要担心取消。如果调用堆栈更深,则顶部的 MethodA 和用户输入点的 MethodB 之间的任何方法都不需要了解有关取消的任何信息。

另一个好处是 MethodB 可以保留其自然签名。它返回一个字符串。如果发生失败,无论是由于更传统的异常还是用户取消,都会引发异常。

这个非常简单的示例并不比上一个不使用 Abort 的示例更具吸引力。但想象一下,如果 MethodB 在调用堆栈中的深度为 4 或 5,代码会是什么样子?

<小时/>

我绝对不是说应该始终使用Abort 代替exit。我相信两者都有自己的位置。 Abort 的亮点是当用户选择取消操作并且您不希望在当前事件处理程序中进行任何更多处理时。此外,由于用户明确选择取消,因此不需要向他们呈现进一步的 UI。您不需要一个消息框告诉用户他们取消了,他们已经知道了。

关于delphi - 在某些情况下使用 Abort 来改进/简化代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42242107/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com