2015-03-04 11 views
8

Załóżmy, że mam następujące rutynowe:Delphi - Jaka jest "poprawna" kolejność bloków poza i na końcu?

function ReadFile(f : TFilename) : Boolean; 
var 
    fs : TFileStream; 
begin 
    Result := False; 
    try 
    fs := TFileStream.Create(f, ...); 
    try 
     // read file ... 
     Result := True; 
    finally 
     FreeAndNil(fs); 
    end; 
    except 
    // handle exceptions ... 
    end; 
end; 

Jakie są konsekwencje posiadania except i finally transponowane? Widziałem wiele postów z nimi w obie strony, ale nie widziałem jasnego wyjaśnienia, który z nich jest odpowiedni w jakich przypadkach (nadal uważam, że to ciekawe, że w powyższym konstrukcie, blok finally wykonuje po z except blok!).

Widziałem również posty, które sugerują, że mieszanie bloków try..except i try..finally nie jest dobrym pomysłem. Jak można tego uniknąć w sytuacjach, gdy rutyna zgłasza wyjątek w ramach normalnej operacji - na przykład w niektórych procedurach Indy?

+3

* "w powyższym konstrukcie blok finally jest wykonywany po bloku except" * - To nie jest poprawne. –

Odpowiedz

11

Nie ma jednego prawidłowego sposobu, aby to zapisać. Te dwa warianty robią różne rzeczy. Możesz preferować jedną wersję w jednym scenariuszu, a drugą w innym scenariuszu.

wersji 1, w końcu najbardziej wewnętrznych

function ReadFile(f : TFilename) : Boolean; 
var 
    fs : TFileStream; 
begin 
    Result := False; 
    try 
    fs := TFileStream.Create(f, ...); 
    try 
     // read file ... 
     Result := True; 
    finally 
     FreeAndNil(fs); 
    end; 
    except 
    // handle exceptions ... 
    end; 
end; 

Version 2, w końcu zewnętrznej najbardziej

function ReadFile(f : TFilename) : Boolean; 
var 
    fs : TFileStream; 
begin 
    Result := False; 
    fs := TFileStream.Create(f, ...); 
    try 
    try 
     // read file ... 
     Result := True; 
    except 
     // handle exceptions ... 
    end; 
    finally 
    FreeAndNil(fs); 
    end; 
end; 

Różnicę stanowi to, w jaki sposób kod podejmuje gdy TFileStream.Create podnosi wyjątek daleko od nieprawdopodobnej ewentualności. W wersji 1 wyjątek zostanie przechwycony i obsłużony wewnątrz ReadFile. W wersji 2 wyjątek zostanie usunięty z ReadFile i dalej w łańcuchu obsługi wyjątków.

Wydzielone

można podać:

Nadal uważam, że to dziwne, że w powyższym konstrukcie, w końcu bloku wykonuje po wyjątkiem bloku!

To nie jest prawda w przypadku kodu w pytaniu, wersja 1 powyżej. Być może jeszcze nie w pełni rozumiesz, jak działają ostatecznie i blokowe.

Powszechnie popełnianym błędem jest chęć złapania wyjątków w jak najszybszym terminie. To zła strategia. Cała uwaga dotycząca wyjątku jest taka, że ​​nie ma to miejsca i zwykle nie wiesz, co zrobić, gdy to nastąpi. Twoim celem jest obsługa wyjątków tak późno, jak to możliwe. Dla ogromnej większości kodu po prostu nie należy traktować wyjątków. Niech płyną w górę do punktu w kodzie, który jest w stanie poradzić sobie z błędem.

+0

OK, myślę, że się mylę w kolejności wykonania. Byłem pewien, że przetestowałem go, przechodząc przez rutynę, gdy zajmował się uwięzionym wyjątkiem, ale chyba nie. Dzięki za odpowiedź. Ładne i dokładne. – rossmcm

Powiązane problemy