Использование вложенных операторов "try / finally" и "try / Кроме" - PullRequest
1 голос
/ 20 августа 2010

Я видел этот код, размещенный здесь на StackOverflow:

with TDownloadURL.Create(nil) do
  try
    URL := 'myurltodownload.com';
    filename := 'locationtosaveto';
    try
      ExecuteTarget(nil);
    except
      result := false;
    end;
    if not FileExists(filename) then
      result := false;
  finally
    free;
  end;

Разве это не может быть упрощенно выглядеть так:

 Result:= FALSE;               <--------- Compiler complains
 DeleteFile(Dest);
 dl:= TDownloadURL.Create(NIL);
 TRY
   dl.URL:= URL;
   dl.FileName:= Dest;
   dl.ExecuteTarget(NIL);           
   Result:= FileExists(Dest);
 FINALLY
   dl.Free;
 END;

Окончательный результат: = ... никогда не будет выполнен, если что-то пошло не так в «ExecuteTarget», потому что программа перейдет непосредственно к «finally». Правильно? Итак, функция вернет FALSE. Я что-то не так делаю?


PS:

  1. Я собираюсь использовать этот код в потоке.
  2. Я просто поместил функцию в Delphi, и компилятор жалуется на первую строку: «Назначенное значение никогда не используется».

Ответы [ 3 ]

12 голосов
/ 20 августа 2010

Разница в том, что ваш второй пример передает исключения вызывающей стороне, в то время как оригинал перехватывает их и возвращает false.Я бы охарактеризовал этот стиль кодирования как «мне все равно, почему он потерпел неудачу, меня интересует только, добился ли он успеха».Что может быть разумным в некоторых случаях (например, попытка загрузить обновление).

Таким образом, ваш код сильно отличается от исходного в этом отношении - вы ожидаете, что вызывающая сторона будет обрабатывать исключения, которых нет в исходном коде.

Кроме того, жалоба компилятора заключается в том, что ветки нетв вашем коде - либо, если работает и результат определяется вторым назначением, либо у вас есть исключение, и Результат не имеет значения.

Result := FALSE; //   <--------- Compiler complains
DeleteFile(Dest);
dl := TDownloadURL.Create(nil);
try
   dl.URL := URL;
   dl.FileName := Dest;
   dl.ExecuteTarget(nil);
   Result := FileExists(Dest);
finally
   dl.Free;
end;
2 голосов
/ 20 августа 2010

В оригинале, если ExecuteTarget выдает исключение, он все равно будет проверять, существует ли имя файла.

В вашем случае, если ExecuteTarget выдает исключение, результат всегда ложен.

Кроме того, если вы не пропустили строку в оригинале, если ExecuteTarget успешно выполняется и файл существует, resultникогда не устанавливается.

1 голос
/ 20 августа 2010

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

...