Когда я должен использовать блоки try и какой тип я должен использовать?

Два очень простых вопроса об обработке исключений в Delphi.

1) Когда Try? Я предполагаю, что мне не нужно предложение Try вокруг

  • простой код, такой как присваивания, условные операторы и циклы
  • доступ к моим компонентам VCL

но мне нужно Try

  • доступ к базе данных
  • любые сторонние компоненты, так как я не знаю, могут ли они вызвать исключение или нет
  • все, что показывает справочная система, может вызвать исключение

Я что-то пропустил?

2) Попробовать... Наконец или Попробовать... Кроме... или и то, и другое? В течение многих лет я думал, что это выбор «или/или», пока @RRUZ не ответил один из моих вопросов с некоторым кодом, который

 try
    CoInitialize(nil);
    try
      SetStaticIpAddress('Network card name','192.168.1.1','255.255.255.0');
    finally
      CoUninitialize;
    end;
 except
    on E:EOleException do
        Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;

Вопрос: за исключением того, что исключения будут перехватываться только из CoInitialize(nil); или также из SetStaticIpAddress('Network card name','192.168.1.1','255.255.255.0');?

Иными словами, возможно ли получить свой пирог и съесть его, если в конце концов удастся превзойти попытку за исключением попытки?


[обновить] ответ на № 2, кажется, да. Этот код показывает оба диалоговых окна...

procedure TForm3.FormCreate(Sender: TObject);
  var x, zero : Integer;
begin
   zero := 0;
   try
      try
        x := 42 div zero;
      finally
         MessageDlg('Divide by zero finally', mtInformation, [mbOK], 0);
      end;

   Except
     on E: Exception do
     MessageDlg('Divide by zero exception handled', mtInformation, [mbOK], 0);
   end;
end;

person Mawg says reinstate Monica    schedule 26.09.2012    source источник
comment
Почему вы вообще пытаетесь обрабатывать эти исключения. Не берись за них.   -  person David Heffernan    schedule 26.09.2012
comment
Некоторые мысли: 1. Try...finally используется для обеспечения высвобождения выделенных ресурсов в случае возникновения исключения. 2.) Не существует общего правила при использовании блока try...except, который полностью зависит от дизайна вашего кода. метод не имеет обработчика исключений.   -  person RRUZ    schedule 26.09.2012
comment
Чтобы уточнить, вам обычно не нужно писать try/except. Обычно это означает, что что-то пошло не так, и никакие обработки не могут исправить эту ошибку. Исключения, ну, исключительные. Пусть исключения всплывают на верхний уровень. Теперь try/finally используется для защиты ресурсов. Например, вы выделяете память, а затем должны убедиться, что она впоследствии будет освобождена, несмотря ни на что. Это finally.   -  person David Heffernan    schedule 26.09.2012
comment
Продолжая идею о том, что исключения являются исключительными. Если вы этого ожидаете, пусть это не будет исключением. Если вы можете справиться с этим на месте, сделайте это на месте. Только если вы не можете справиться с этим, сделайте это исключением. И тогда, конечно, вы не справитесь с этим, потому что не можете. Если вы делите на что-то, что может быть нулем, проверьте наличие нуля, прежде чем пытаться делить. Если вы считаете, что делитель не может быть равен нулю, разделите. Но не обрабатывать исключения. Конечно, иногда вам нужно с ними справиться, но почти всегда нет.   -  person David Heffernan    schedule 26.09.2012
comment
@DavidHeffernan 2 @ +1, но я признаю, что подумал, что ваш первый комментарий был шуткой :-/ Я могу понять вашу философию Если вы этого ожидаете, пусть это не будет исключением, но я не могу контролировать третью сторону код, который я вызываю, большая часть которого будет создавать исключения. И я согласен с тем, что никакая обработка не может отменить этот сбой, например, у меня может быть временное состояние, такое как сбой базы данных или сетевого подключения, и я могу изящно восстановиться. Некоторые приложения не могут позволить себе роскошь остановить работу. Но мне нравится, что ваш наконец используется для защиты ресурсов.   -  person Mawg says reinstate Monica    schedule 26.09.2012
comment
@RRZUZ +1. Спасибо. В моем обновленном сообщении с кодом показано то, что вы объяснили. Теперь я начинаю понимать, и мне нравится подход с поясом и берцами. finally обеспечивает освобождение ресурсов как для успеха, так и для неудачи, тогда как except позволяет мне регистрировать информацию или, возможно, информировать пользователя и выполнять общую обработку ошибок.   -  person Mawg says reinstate Monica    schedule 26.09.2012
comment
Теперь, что насчет моего первого вопроса — какие вещи могут генерировать исключения и требуют предложения Try, а какие нет? Или вы рекомендуете использовать Try для каждой функции во всем коде? Если нет, то как вы решаете?   -  person Mawg says reinstate Monica    schedule 26.09.2012
comment
@DavidHeffernan: Бывают случаи, когда у вас нет другого выбора, кроме как поймать исключение - все, что может измениться между моментом проверки и выполнением операции. Наиболее распространенным примером этого является обработка файлов.   -  person Loren Pechtel    schedule 26.09.2012
comment
@David: Еще одна догма. Вы просто не можете делать общие заявления, такие как Не обрабатывать исключения. Некоторые библиотеки классов специально используют исключения в качестве механизма сообщения об ошибках, а иногда просто более эффективно — и более логически правильно (что вы должны оценить) — обрабатывать исключения, а не упреждающе обрабатывать их. условия, которые приводят к ним или позволяют им уйти вверх по стеку. то есть я не ожидаю этого, но я могу справиться с этим, если это произойдет.   -  person Deltics    schedule 26.09.2012
comment
@Deltics Я сказал: Конечно, иногда вам нужно справиться с ними, но почти всегда нет.   -  person David Heffernan    schedule 26.09.2012
comment
Конечно, в конце концов вы сказали это после того, как дважды перед тем, как довольно четко выразить мысль о том, что исключения не должны обрабатываться. Сначала абсолютно, а потом слегка отступив и начав формулировать вещи в терминах обычно, и даже тогда вы цеплялись за мысль, что догматический подход почти всегда правильный. Я думаю, иногда даже самые догматичные люди вынуждены отказываться от разума, когда они просто не могут избежать его, хотя и неохотно. ;)   -  person Deltics    schedule 03.10.2012


Ответы (1)


Хотя они оба относятся к обработке исключений, они разные звери.

Попробуйте... Наконец, для очистки ресурсов. Его всегда следует использовать при выделении ресурсов, которые очищаются в конце подпрограммы. (Толкуйте «ресурсы» здесь в широком смысле — они нужны вам также для таких вещей, как замки и т. д.)

Try...Except предназначен для перехвата исключений. Используйте его только тогда, когда может случиться исключение, с которым у вас есть разумный способ справиться. Вы почти никогда не должны просто захватывать все исключения, кроме как в рамках средства регистрации ошибок верхнего уровня. (Я не говорю, что вы никогда не должны перехватывать все — например, вы читаете конфигурационный файл, и это плохо. Единственный реальный выбор — прервать программу или подать крик, использовать значения по умолчанию и продолжить. В целом пользователи, вероятно, предпочтут последний.)

Они могут быть вложены на любую глубину (когда вы выделяете несколько ресурсов, вы либо должны их вложить, либо у вас должен быть какой-то способ выяснить, был ли ресурс получен или нет, прежде чем отпустить его) и свободно сосуществовать.

person Loren Pechtel    schedule 26.09.2012
comment
{+1 Да, я склоняюсь к такому образу мыслей. Как я сказал RRUZ выше, мой обновленный пост с кодом показывает то, что вы объяснили. Теперь я начинаю понимать, и мне нравится подход с поясом и берцами. Функция finally гарантирует, что ресурсы будут освобождены как для успеха, так и для неудачи, тогда как исключение позволяет мне регистрировать информацию или, возможно, информировать пользователя и выполнять общую обработку ошибок. - person Mawg says reinstate Monica; 26.09.2012
comment
Теперь, что насчет моего первого вопроса — какие вещи могут генерировать исключения и требуют предложения Try, а какие нет? Или вы рекомендуете использовать Try для каждой функции во всем коде? Если нет, то как вы решаете? - person Mawg says reinstate Monica; 26.09.2012
comment
@Mawg: Дело не в том, что может вызывать исключения, а в том, от чего вы можете восстановиться. - person Loren Pechtel; 26.09.2012
comment
+1 Но я хотел подчеркнуть, что стоит ли ставить блоки Try вокруг всего? Ты? Я думаю, имеет смысл только попробовать что-то, что может вызвать исключение; что это за штука? Или, другими словами, есть ли что-нибудь, что не может вызвать исключение? - person Mawg says reinstate Monica; 26.09.2012
comment
@Mawg: у тебя это наоборот. Вы только помещаете блоки try...except вокруг вещей, где вы можете разумно обработать исключение. Если вы не можете спланировать конкретное исключение и то, что вы хотите с ним сделать, вы все равно не должны его перехватывать, кроме как для целей ведения журнала. Если что-то пошло не так, чего вы не ожидали, вам, вероятно, не следует продолжать запускать программу — это требует повреждения данных. - person Loren Pechtel; 26.09.2012
comment
+1 Я понимаю твою точку зрения. Но кажется, что вы хотите, чтобы пользователь увидел фейерверк, а не вежливое сообщение о том, что что-то пошло не так (логирование ответа было бы полезно). Кроме того, если у меня есть критически важное приложение, я могу смириться с тем, что некоторые подфункции не работают, пока работает ядро. Например, мой аппарат ЭКГ должен продолжать работать, даже если я не могу сохранить файл. - person Mawg says reinstate Monica; 26.09.2012
comment
Если вы решите следовать предложениям предыдущих комментаторов: (1) используйте try/except только в тех местах, где вы можете правильно обрабатывать исключения, и (2) используйте try/finally для очистки ресурсов, тогда я предлагаю вам взглянуть на Алистера Кристи. ролик об исключениях в конструкторах/деструкторах [codegearguru.com/video/030/TSuicide.html] и как с ними справиться. Он использует только блоки try/finally и оставляет обработку исключений приложению. Он объясняет различные варианты, которые у вас есть, и расширяет их до создания более одного объекта. - person Jan Doggen; 26.09.2012
comment
Удачи вам в переносе каждой отдельной подпрограммы в try/except. Затем, когда вы перехватили и обработали исключение, что дальше. Подпрограмма возвращается к вызывающей стороне, но что она собирается делать дальше? Если вызываемый абонент не мог выполнить свою работу, вероятно, вызывающий абонент застрял. Это не может продолжаться. Исключения не предназначены для обработки в самом низком возможном месте. Они должны быть пойманы и обработаны в тот момент, когда приложение знает, что с ними делать. Если сообщение необходимо показать пользователю, пусть исключение всплывает прямо вверху, где сообщение может быть показано. - person David Heffernan; 26.09.2012
comment
@Mawg: Мы не возражаем против обработчика ошибок верхнего уровня, который вежливо сообщает, что что-то пошло не так, вот почему я умираю. Что касается вашей машины ЭКГ, ошибки ввода-вывода файла — это то, что вы можете предвидеть и реагировать на них разумным образом. - person Loren Pechtel; 26.09.2012