Самый простой сценарий, который иллюстрирует мою точку зрения, как так:
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
, возможно, должно быть передано на большое количество уровней. Это станет громоздким.
Или подумайте, что произойдет, если MethodB
должно вернуть значение своему вызывающему абоненту. В этом сценарии исходный код может быть таким:
procedure MethodA;
begin
MethodC(MethodB);
end;
function MethodB: string;
begin
Result := ...;
end;
procedure MethodC(Value: string);
begin
// ... do stuff with Value
end;
Теперь еще раз подумайте, что произойдет, если пользователь получит шанс отменить. Как мы можем вернуть логическую строку и строку из MethodB
? Используя параметр out для одного из возвращаемых значений? Использование составной структуры, такой как запись, для переноса обоих значений. Последнее, очевидно, включает в себя множество шаблонов, поэтому давайте рассмотрим первое.
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;
Конечно вы можете сделать это, но это начинает выглядеть как своего рода код, который исключения были разработаны для упрощения. И на этом этапе рассмотрим существование молчащего исключения, EAbort
, поднятого вызовом Abort
, что не приводит к сообщению, отображаемому обработчиком исключений верхнего уровня. Последняя точка - это то, что имеется в виду под номером silent.
Теперь код становится:
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
может сохранять свою естественную подпись. Он возвращает string
. В случае отказа, либо от более традиционного исключения, либо от отмены пользователя, генерируется исключение.
Этот очень простой пример не настолько убедительнее, чем предыдущий, который не использует Abort
. Но представьте, как выглядел бы код, если бы MethodB
были на 4 или 5 глубины в стеке вызовов?
Я абсолютно не говорю, что Abort
всегда должен использоваться вместо exit
. Я убежден, что оба имеют свое место. Где Abort
shines - это когда пользователь выбирает отмену операции, и вы не хотите, чтобы в текущем обработчике событий больше не выполнялась обработка. Кроме того, поскольку пользователь явно отказался от отмены, дальнейший пользовательский интерфейс не должен быть представлен им. Вам не требуется окно с сообщением пользователю о том, что они отменены, они уже знают это.
Я действительно сочувствую вам, поскольку вы видели, что я тот, кто предложил функцию выхода, и Дэвид упомянул об этом ... «Случается, что вы иногда извлекаете код в другой метод, а затем выходите только отменяет этот метод. Abort устойчив к таким изменениям », и это не придало мне больше света. – Fero
@Fero Method Метод вызовов B вызывает метод C. Метод C делает ранний выход. Но тогда B должен сделать то же самое. И так же A. –
Хорошо, но это будет только зависеть от того, что делает ваш метод? потому что, если ваш метод ничего не возвращает, я не вижу проблемы ... – Fero