2015-03-04 16 views
8

Supponiamo che io ho le seguenti impostazioni:Delphi - Qual è l'ordine "corretto" per i blocchi eccetto e infine?

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; 

quali sono le implicazioni di avere il except e finally recepite? Ho visto molti post con entrambi i metodi, ma non ho visto una chiara spiegazione di quale sia appropriato in quali casi (penso ancora che sia curioso che nel precedente costrutto, il blocco finally esegua dopo il except bloccare!).

Ho anche visto post che suggeriscono che la combinazione di blocchi try..except e try..finally non è una buona idea. Come puoi evitarlo in situazioni in cui una routine genera un'eccezione come parte del normale funzionamento, come in alcune delle routine di Indy?

+3

* "nel costrutto sopra, il blocco finally viene eseguito dopo il blocco tranne" * - Non è corretto. –

risposta

11

Non esiste un unico modo corretto per scrivere questo. Le due varianti fanno cose diverse. Potresti preferire una versione in uno scenario, l'altra in uno scenario diverso.

Versione 1, infine più interna

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; 

versione 2, infine più esterno

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; 

La grande differenza è come il codice si comporta se TFileStream.Create solleva un'eccezione, un'eventualità tutt'altro che plausibile. Nella versione 1, l'eccezione verrà catturata e gestita all'interno di ReadFile. Nella versione 2, l'eccezione verrà passata da ReadFile e nella catena di gestori di eccezioni.

Asides

È stato:

Io continuo a pensare che è curioso che nel costrutto sopra, il blocco finally viene eseguito dopo l'eccezione di blocco!

Questo non è vero per il codice nella tua domanda, versione 1 sopra. Forse non capisci ancora bene come funzionano finalmente i blocchi.

Un errore comune che viene spesso osservato è il desiderio di rilevare e gestire le eccezioni il prima possibile. Questa è la strategia sbagliata. Il punto su un'eccezione è che non è pensato per accadere e di solito non sai cosa fare quando succede. Il tuo obiettivo è gestire le eccezioni il più tardi possibile. Per la stragrande maggioranza del codice non dovresti semplicemente gestire le eccezioni. Lasciali fluttuare verso l'alto fino a un punto nel codice che è in grado di gestire l'errore.

+0

Ok, immagino di essere in errore nell'ordine di esecuzione. Ero certo di averlo provato passando da una routine mentre gestiva un'eccezione intrappolata, ma non credo. Grazie per la tua risposta. Bello e completo. – rossmcm