В delphi 7 это `попробовать ... кроме как поднять;конец;`вообще имеет смысл?

StackOverflow https://stackoverflow.com/questions/805109

Вопрос

В некотором коде Delphi 7, который я поддерживаю, я заметил множество примеров следующего:

with ADOQuery1 do begin
  // .. fill out sql.text, etc
  try
    execSQL;
  except
    raise;
  end;
end;

Мне кажется, что эти блоки try можно было бы удалить, поскольку они ничего не делают.Тем не менее, я опасаюсь возможных незначительных побочных эффектов..

Кто-нибудь может вспомнить какие-либо случаи, в которых эти блоки действительно могли бы делать что-то, чего не произошло бы без них?

Это было полезно?

Решение

В этом контексте операция повышения не имеет никакого эффекта и должна быть удалена, потому что она просто повторно создает исключение, которое только что перехватил блок исключений.повышение обычно используется для передачи управления в конец блока, когда недоступна соответствующая обработка ошибок.Далее мы обрабатываем пользовательское исключение, но любое другое исключение должно обрабатываться в другом месте.

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 из приведенного выше фрагмента кода не будет иметь никакого значения.Ты можешь (и я тебе верю следует поскольку это снижает читабельность) удалите его.

Ладно, на самом деле здесь два вопроса.

Во-первых, это является значимый:если ExecSQL выдает исключение, оно перехватывается блоком try и пересылается в except.Затем он перенаправляется путем повышения ставки на следующий более высокий блок.

Во-вторых, это полезный?Скорее всего, нет.Это почти наверняка является результатом одной из трех причин:

  1. Кто-то с заостренными волосами написал стандарт кодирования, в котором говорилось: "все операции, которые могут вызвать исключение, должны быть в блоке try".
  2. Кто-то намеревался вернуться и отменить исключения, сделанные execSQL включение в какое-то другое, более значимое исключение.
  3. Кто-то новый не знал, что то, что они написали, было изоморфно тому, чтобы позволить uter environment беспокоиться об исключении, и поэтому подумал, что они должен перешлите это.

Возможно, я ответил немного поспешно, смотрите в конце...
Как бы то ни было, это бесполезно для приложения.
Точка!

Теперь перейдем к вопросу "почему".Это может быть для стандартизации обработки исключений, если там / был / будет / есть в других местах / какой-то код протоколирования, вставленный перед повышением:

  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 строка, чтобы получить возможность увидеть, что происходит в контексте этого блока кода.

Этот код ничего не делает, кроме как позволяет оригинальному программисту установить точку останова при "Повышении" и увидеть исключение ближе в исходном коде к его возможной причине.В этом смысле это вполне разумный метод отладки.

На самом деле, я должен был опубликовать это как комментарий к ответам Франсуа, но я не знаю, возможно ли вставить туда форматированный код: (Поэтому я публикую это как ответ.

2 мгхи:

Второй вариант полностью однотипен, вместо него можно было бы использовать 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" - функция всегда будет возвращать nil.Если вы вообще опустите блок "try" - в случае исключения в "..." произойдет утечка ресурсов.

P.S.Конечно, вы можете использовать "finally" и проверить ExceptObj, но...разве это не уродливо?

Название содержит довольно широкий вопрос, в то время как в его объяснении приводится более конкретный пример.Итак, мой ответ на вопрос о том, как это вытекает из примера, вряд ли может добавить что-либо полезное к тому, что здесь уже было сказано.

Но, может быть Блоргбородый действительно хочет знать, так ли это вообще значимый для try ... except raise; end.В Delphi 7, если я правильно помню, Exit это вызвало бы finally часть try-finally блокировать (как будто это было какое-то исключение).Кто-то может счесть такое поведение неподходящим для своей задачи, и использование рассматриваемой конструкции является вполне обходным путем.

Только все равно было бы странно использовать один raise; вот так, но тогда нам следовало бы поговорить о Полезность вместо того , чтобы осмысленность, как метко заметил Чарли.

Этот код ничего не делает, кроме повторного создания исключения, которое уже будет создано без этого блока try except.Вы можете спокойно удалить его.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top