Страница 2 из 3

Re: Except Or Finally?

Добавлено: 20.06.2011 15:44:49
alex208210
ну и темы у вас)))
Пользую except в любом случае..
В примерах всегда показывают например так:

idhttp1:=idhttp1.create();
try
str:=idhttp1.get('ya.ru');
finally
idhttp1.free;
end;

смысл в том что не зависимо от ситуации (наличие/отсутвие Интернета).. компонент уничтожается.. но если Интернета нет, то пользователь увидит не очень хорошее сообщение с красным крестиком ААААА ОШИБКА!!!!

idhttp1:=idhttp1.create();
try
str:=idhttp1.get('ya.ru');
idhttp1.free;
except
idhttp1.free;
showmessage('Упс походу инета нет');
end;

в этом случает пользователь увидит повод поматериться, но съэкономит кучу нервов, не пугуясь ОШИБКИ!!!!

И плодить кучу блоков друг в друге не вижу удобным и наглядным для понимания кодом

Re: Except Or Finally?

Добавлено: 20.06.2011 15:53:17
Max Rusov
Обычно - как раз наоборот: много вложенных try-finally, а снаружи - try-except.

Код: Выделить всё

try
  АллоцируемРесурс1;
  try
    //...
    АллоцируемРесурс2;
    try
       //...
    finally
      ОсвобождаемРесурс2;
    end;
    //...
  finally
    ОсвобождаемРесурс1;
  end;

except
  ОбрабатываемОшибку;
end;


Конечно, обычно, вложенные try-finally находятся в вызываемых процедурах, я "распрямил" для наглядности.

Добавлено спустя 5 минут 57 секунд:
Еще неочевидной особенностью try-finally является то, что управление попадет в finally блок, даже если исполнение процедуры прекращается по exit (или цикла по break). Правда - насчет goto - не уверен :).

Код: Выделить всё

procedure Some;
begin
  АлолцируемРесурсы;
  try
     //...
     if КакоеТоУсловие then
       Exit; // Все равно попадем в finally часть, хоть это и не исключение.
     //...
  finally
    ОсвобождаемРесурсы;
  end;
end;

Re: Except Or Finally?

Добавлено: 20.06.2011 15:58:18
alex208210
все же удобнее и понятнее будет

Код: Выделить всё

try
if КакоеТоУсловие then
   begin
    выполняем_действие;
    ОсвобождаемРесурсы;
    exit;
   end;
except
   ОсвобождаемРесурсы;
   exit;
end;

Re: Except Or Finally?

Добавлено: 20.06.2011 15:59:23
Max Rusov
OMG :(

Re: Except Or Finally?

Добавлено: 20.06.2011 16:05:32
ronin
Принципиальна разница как раз в том, что finally _не_ подавляет exception, исполнение алгоритма прерывается, он проходит по всем вложенным Finally частям пока не попадет в завершающий Except. Без finally на одних except'ах этого очень тяжело добиться


я посмотрел на тестовом примере, при исключительной ситуации finally подавил вывод сообщения об ошибке, аналогично exception'у, так что я сам в раздумье в чём разница о_О

Re: Except Or Finally?

Добавлено: 20.06.2011 16:14:33
Max Rusov
Пример в студию.

Re: Except Or Finally?

Добавлено: 20.06.2011 16:18:46
alex208210
ronin обманывать не хорошо)

Re: Except Or Finally?

Добавлено: 20.06.2011 16:42:30
evd
Не всегда имеет смысл обрабатывать исключения в каждой процедуре/методе.
Например:

Код: Выделить всё

//Одна из множества процедур, вызываемая из RunBigOperation
procedure SomethingWrong;
begin
  //Выделяем память
  try
   ........
   raise Exception.Create('Что-то пошло не так');
  finally
   //Освождаем память
  end;
end;

procedure RunBigOperation();
begin
   try
      SomethingWrong();
   except
      //Большой код обработки исключения
   end;
end;


В данном примере в процедуре выполниться блок finally, а затем пойдет в except процедуры RunBigOperation, где ошибка и обработается
К тому же не всегда имеет смысл в процедуре ловить все исключения

Re: Except Or Finally?

Добавлено: 20.06.2011 16:51:23
Max Rusov
Вообще, в 99% случаев не требуется писать except, всегда есть корневой except в базовых библиотеках. Свой except надо писать только если по каким-то причинам не устраивает стандартная обработка исключения. Это очень редко.

Re: Except Or Finally?

Добавлено: 20.06.2011 21:48:32
daesher
Max Rusov писал(а):Вообще, в 99% случаев не требуется писать except, всегда есть корневой except в базовых библиотеках. Свой except надо писать только если по каким-то причинам не устраивает стандартная обработка исключения. Это очень редко.

Ну почему редко? Практически всегда, когда мы знаем, что на этом участке в достаточно штатной ситуации может быть ошибка (идеально, конечно, поймать её условиями, но не всегда оно того стоит). Пользователь будет совсем не рад отвечать на вопрос о том, снять ли приложение или продолжить выполнение.
А иногда бывает, что некоторые действия можно было бы выполнить, но это не суть как важно, если что-то там сорвётся; сообщать пользователю о таких мелочах совсем не стоит.

Добавлено спустя 6 минут 10 секунд:
Чтобы не быть голословным: допустим, мы строим график функции, функция задаётся в виде переменной процедурного типа или даже события (возможно, она программируется совершенно другим пользователем, которому, разумеется, лень проводить проверку на ОДЗ, и тем более не удобно передавать как-то результат этой проверки); в какой-то области функция не существует. Логично, что на каждую такую точку при каждой перерисовке графика программа ругаться не должна; было бы идеально, чтобы точка просто не строилась! И она не будет строиться, если заключить её (вызов функции и построение точки) в блок try...except...end. Единственное, между except и end, по большому счёту, и ставить нечего.

Re: Except Or Finally?

Добавлено: 20.06.2011 22:54:07
Odyssey
daesher писал(а):Ну почему редко? Практически всегда, когда мы знаем, что на этом участке в достаточно штатной ситуации может быть ошибка

Вот по-хорошему, такие случаи должно быть очень редко :) Потому что исключения, по определению, предназначены для исключительных, т.е. нештатных ситуаций.

daesher писал(а):А иногда бывает, что некоторые действия можно было бы выполнить, но это не суть как важно, если что-то там сорвётся; сообщать пользователю о таких мелочах совсем не стоит.

Тут согласен, хотя нужно очень чётко фильтровать "мелочи" от не мелочей, т.е.

Код: Выделить всё

try
  // SomeAction
except
  on E: ESmallException do begin end;
end;

Если использовать просто "except end;" - можно вместе с мелочами пропустить серьёзную проблему, например чреватую потерей данных.

Re: Except Or Finally?

Добавлено: 20.06.2011 23:48:57
Max Rusov
Посмотрел, ради интереса, в своих исходниках. Слово "finally" Встресается ~7600 раз, слово "except" ~2700. В исходниках VCL приблизительно то же соотношение 3:1. Видимо - закон природы :)

Re: Except Or Finally?

Добавлено: 21.06.2011 00:22:34
Widowmaker
Видимо, наипростейший случай:

Код: Выделить всё

//...
fdata : TextFile; // текстовый файл для чтения / записи информации
  begin
    err_code := 0;
    //
    case ( opmode_ ) of
      1 : // чтение данных
        begin
          AssignFile ( fdata, filename_ );
          //
          {$I-} // передаём контроль ошибок ввода/вывода программе
          Reset ( fdata );
          {$I+} // восстанавливаем автоматический контроль ошибок ввода/вывода
          //
          if ( IOResult <> 0 ) then
            begin
              err_code := -101;
              exit ( err_code ); // выход
            end; // if ( IOResult <> 0 )
          // если файл данных существует и открылся
  //...
      end;
  //...
  end;

Стало интересно, можно ли обойтись без {$I-} ... {$I+}. Пробовал и try ... except, и try ... finally, однако пока не поставил {$I-} ... {$I+}, программа вываливалась с сообщением об ошибке открытия файла, если его на диске не было, чего и следовало ожидать. Ваял много чего ещё, но и в других случаях, в том числе и в С++, нужды в этих конструкциях тоже ни разу не возникло. Наверное, они были придуманы специально в декоративных целях -- для украшения кода и придания ему большего наукообразия. :lol:

Re: Except Or Finally?

Добавлено: 21.06.2011 02:32:31
Sergei I. Gorelkin
Класс Exception и (почти) вся обработка исключений находятся в модуле sysutils. В простейших программах без использования sysutils исключения работать не будут.

Re: Except Or Finally?

Добавлено: 21.06.2011 03:36:21
Widowmaker
Так в том-то и дело, что SysUtils используется :

Код: Выделить всё

unit GSW;
//
{$mode objfpc}{$H+}
//
interface
//
uses
  Classes, SysUtils, {FileUtil}, MedFilter;
type
  TGSW = class ( TObject )
  //
//...
end; // type

, однако получается, что директивы {$I-} ... {$I+} нужны безотносительно к способу обработки ошибки открытия несуществующего файла.