В delphi 7 "try ... except raise; end;" вообще имеет смысл?
в некотором коде Delphi 7, который я поддерживаю, я заметил много экземпляров следующего:
with ADOQuery1 do begin
// .. fill out sql.text, etc
try
execSQL;
except
raise;
end;
end;
Мне кажется, что эти блоки могут быть удалены, так как они ничего не делают. Однако я опасаюсь возможных побочных эффектов..
может ли кто-нибудь подумать о каких-либо случаях, когда эти блоки действительно могли бы сделать что-то, что не произошло бы без них?
8 ответов
в этом контексте операция raise не имеет никакого эффекта и должна быть удалена, потому что она просто повторно вызывает исключение, которое блок исключения только что поймал. рейз обычно используется для передачи управления в конец блока, когда нет надлежащей обработки ошибок. В следующем мы обрабатываем пользовательское исключение, но любое другое исключение должно обрабатываться в другом месте.
try
someOperation;
except
on e: ECustomException do
SomeCustomHandelr;
else
begin
// the raise is only useful to rethrow the exception to an encompasing
// handler. In this case after I have called my logger code. as Rob
// mentioned this can be omitted if you arent handling anything because
// the compiler will simply jump you to the next block if there is no
// else.
LogUnexpectedException('some operation failed',e);
raise;
end;
end;
будьте осторожны, что есть аналогичная форма без "повышения", которая имеет побочный эффект еды / скрывать любые исключения. практики очень недобросовестных разработчиков, которые, надеюсь, перешли на позиции с конкурентами.
with ADOQuery1 do begin
// .. fill out sql.text, etc
try
execSQL;
except
// no handler so this just eats any "errors"
end;
удаление кода except в приведенном выше фрагменте кода не будет иметь никакого значения. Вы можете (и я верю вам должны так как это уменьшает читаемость) удалите его.
хорошо, здесь действительно два вопроса.
во-первых, это is meaningful: если execSQL выдает исключение, оно перехватывается блоком try и перенаправляется в except. Затем он переадресовывается повышением в следующий более высокий блок.
во-вторых, это полезное? Скорее всего, нет. Почти наверняка это результат одной из трех вещей:--2-->
- кто-то с заостренными волосами написал стандарт кодирования, который сказал: "Все операции, которые могут исключение должно быть в блоке try."
- кто-то хотел вернуться и повернуть исключения сделаны
execSQL
заявление в какое-то другое, более значимое, исключение. - кто-то новый не знал, что то, что они написали, было изоморфным, чтобы позволить среде uter беспокоиться об исключении, и поэтому они думали, что должны вперед.
возможно, я ответил Слишком быстро, см. В конце...
как это, это бесполезно для приложения.
Точка!
Теперь на стороне "почему". Это может быть стандартизация обработки исключений, если есть /был/будет/ есть в других местах / какой-то код журнала, вставленный перед повышением:
try
execSQL;
except
// Log Exception..
on E: Exception do
begin
LogTrace(Format('%s: Exception Message[%s]',[methodname, E.Message]));
raise;
end;
end;
или для подчистки кода:
try
execSQL;
except
//some FreeAndNil..
raise;
end;
обновление: был бы 1 случай, когда я бы увидел некоторое использование так же, как это есть...
... чтобы иметь возможность поставить точку останова на raise
строка, чтобы получить возможность увидеть, что происходит в контексте этого блока кода.
этот код ничего не делает, кроме как позволяет оригинальному программисту разместить точку останова на "Рейзе" и увидеть исключение ближе в источнике к его возможной причине. В этом смысле это вполне разумная отладочная техника.
на самом деле, я должен опубликовать это как комментарий к ответам Франсуа, но я не знаю, можно ли вставить форматированный код там :( поэтому я публикую это как ответ.
2mghie:
второй полностью unidiomatic, один будет использовать, наконец, вместо этого.
нет, "finally"всегда будет объектом очистки. "Кроме" - только на исключение. Рассмотрим случай функции, которая создает, заполняет и возвращает объект:
function CreateObj: TSomeObj;
begin
Result := TSomeObj.Create;
try
... // do something with Result: load data, fill props, etc.
except
FreeAndNil(Result); // oops: bad things happened. Free object to avoid leak.
raise;
end;
end;
Если вы поставите "finally" там-функция всегда будет возвращать ноль. Если вы вообще опустите блок "try" - произойдет утечка ресурсов в случае исключения в "...".
P. S. Конечно, вы можете использовать "наконец-то" и проверить ExceptObj, но... разве это не отвратительно?
заголовок содержит довольно обширный вопрос, в то время как его объяснение дает более конкретный пример. Итак, мой ответ на вопрос, как он исходит из примера, несомненно, может добавить что-либо полезное к тому, что уже было сказано здесь.
а, может быть Blorgbeard действительно хочет знать, является ли это на всех смысл try ... except raise; end
. В Delphi 7, Если я правильно помню, Exit
автоматически finally
часть try-finally
блок (как если бы это было какое-то исключение). Кто-то может считать такое поведение неуместным для своей задачи, и использование рассматриваемой конструкции является довольно обходным путем.
только это все равно было бы странно использовать один raise;
есть, но тогда мы должны были поговорить о полезность, а не осмысленности, как аккуратно заметил Чарли.
этот код ничего не делает, кроме повторного вызова исключения, которое будет уже создано без этой попытки, кроме блока. Вы можете безопасно удалить его.