In delphi 7, è `prova & # 8230; tranne rilancio; fine; `significativo affatto?
Domanda
In alcuni codici Delphi 7 che sto conservando, ho notato molte delle seguenti situazioni:
with ADOQuery1 do begin
// .. fill out sql.text, etc
try
execSQL;
except
raise;
end;
end;
Mi sembra che questi blocchi di prova possano essere rimossi, poiché non fanno nulla. Tuttavia, sono diffidente nei confronti di possibili effetti collaterali sottili.
Qualcuno può pensare a casi in cui questi blocchi potrebbero effettivamente fare qualcosa che non accadrebbe senza di loro lì?
Soluzione
In questo contesto, l'operazione di rilancio non ha alcun effetto e dovrebbe essere rimossa perché sta semplicemente rilanciando l'eccezione che il blocco di eccezioni ha appena rilevato. in genere viene utilizzato per trasferire il controllo alla fine del blocco quando non è disponibile una gestione degli errori appropriata. Di seguito gestiamo l'eccezione personalizzata, ma qualsiasi altra eccezione dovrebbe essere gestita altrove.
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;
Fai attenzione che esista una forma simile senza il "rialzo" che ha l'effetto collaterale di mangiare / nascondere eventuali eccezioni. pratiche di sviluppatori senza scrupoli che si spera siano passati a posizioni con la concorrenza.
with ADOQuery1 do begin
// .. fill out sql.text, etc
try
execSQL;
except
// no handler so this just eats any "errors"
end;
Altri suggerimenti
La rimozione del codice tranne nello snippet di codice sopra riportato non farà alcuna differenza. Puoi (e credo che dovresti poiché riduce la leggibilità) rimuoverlo.
Okay, davvero due domande qui.
Innanzitutto, è significativo: se execSQL genera un'eccezione, viene catturato dal blocco try e inoltrato all'eccezione. Quindi viene inoltrato dal rilancio al blocco superiore successivo.
Secondo, è utile ? Probabilmente no. Quasi certamente è il risultato di una di queste tre cose:
- Qualcuno con i capelli a punta ha scritto uno standard di codifica secondo il quale "tutte le operazioni che possono generare un'eccezione devono trovarsi in un blocco try."
- Qualcuno voleva tornare e trasformare le eccezioni fatte dalla dichiarazione
execSQL
in qualche altra eccezione più significativa. - Qualcuno di nuovo non era a conoscenza del fatto che ciò che avevano scritto fosse isomorfo nel lasciare che l'ambiente totale si preoccupasse dell'eccezione, e quindi ha pensato che devono inoltrarlo.
Potrei aver risposto un po 'in fretta, vedi alla fine ...
Come è, è inutile per l'applicazione .
Periodo!
Ora sul " perché " lato. Potrebbe essere standardizzare la gestione delle eccezioni se c'era / era / sarà / è in altri luoghi / qualche tipo di codice di registrazione inserito prima del rilancio:
try
execSQL;
except
// Log Exception..
on E: Exception do
begin
LogTrace(Format('%s: Exception Message[%s]',[methodname, E.Message]));
raise;
end;
end;
o per il codice di pulizia:
try
execSQL;
except
//some FreeAndNil..
raise;
end;
Aggiorna : ci sarebbe 1 caso in cui vedrei un uso proprio come è ...
... per poter mettere un Breakpoint sulla linea raise
, per avere la possibilità di vedere cosa sta succedendo nel contesto di quel blocco di codice.
Questo codice non fa altro che consentire al programmatore originale di posizionare un punto di interruzione su "Solleva" e di vedere l'eccezione più vicina nell'origine alla sua possibile causa. In questo senso è una tecnica di debug perfettamente ragionevole.
In realtà, dovrei postarlo come commento alle risposte di François, ma non so è possibile inserire lì un codice formattato :( Quindi sto pubblicando questo come risposta.
2mghie:
Il secondo è completamente unidiomatico, si userebbe invece finalmente.
No, "finalmente". pulirà sempre l'oggetto. & Quot; Tranne " - solo su eccezione. Considera il caso della funzione, che crea, riempie e restituisce un oggetto:
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;
Se inserisci " infine " lì - la funzione restituirà sempre zero. Se ometti " prova " blocca affatto - ci saranno perdite di risorse in caso di eccezione in " ... " ;.
P.S. Ovviamente, puoi utilizzare " infine " e controlla ExceptObj, ma ... non è brutto?
Il titolo contiene una domanda piuttosto ampia, mentre la sua spiegazione fornisce un esempio più specifico. Quindi, la mia risposta alla domanda come procede dall'esempio, può senza dubbio aggiungere qualcosa di utile a ciò che è già stato detto qui.
Ma forse Blorgbeard vuole davvero sapere se è affatto significativo provare ... tranne rilancio; fine
. In Delphi 7, se ricordo correttamente, Exit
attiverebbe la parte finally
di un blocco try-finally
(come se fosse una specie di eccezione). Qualcuno potrebbe considerare tale comportamento inappropriato per il proprio compito e l'utilizzo della costruzione in questione è piuttosto una soluzione alternativa.
Solo sarebbe ancora strano usare un singolo rilancio;
lì, ma poi avremmo dovuto parlare di utilità piuttosto che significatività , come Charlie ha ben osservato.
Questo codice non fa nulla se non il rilanciare un'eccezione che sarà già sollevata senza questo tentativo tranne il blocco. Puoi rimuoverlo in sicurezza.