2009-03-19 13 views
17

Semplice domanda sulle migliori pratiche.C# Nested Prova le istruzioni oi metodi Catch?

Se si nidifica, provare a prendere le istruzioni o utilizzare solo i metodi.

Ad esempio, se si dispone di un metodo che apre un file funziona e chiude il file, si avrà l'apertura e la chiusura all'esterno del try catch, ovvero la chiusura nel blocco finally.

Ora se il metodo aperto non funziona, il metodo dovrebbe affermare correttamente? Quindi dovrebbe essere il vostro involucro che in un blocco catch try o dovrebbe essere chiamato da un altro metodo, che a sua volta come un blocco catch try?

+0

codice di esempio aiuterà illustrare la tua domanda. – Alan

+0

qualsiasi esempio (migliore reale) codice per illustrare la domanda? – Kiquenet

risposta

4

Dipende da ciò che si sta tentando di fare, ma nella maggior parte dei casi, i tentativi di cattura nidificati sono un segno di una funzione eccessivamente complessa (o di un programmatore che non sa come funzionano le eccezioni!).

Nel caso del file aperto, utilizzerei un titolare IDisposable e una clausola using, e quindi rinunciare alla necessità di qualsiasi try/catch esplicito.

7

Questa è una domanda di stile ma per me cerco di non avere più di un livello di try/catch/finalmente nidificazione in un unico metodo. Nel momento in cui premi un tentativo annidato, hai quasi certamente violato il principio operativo 1 funzione = 1 e dovresti utilizzare un secondo metodo.

+3

Penso che in molti, se non nella maggior parte degli sviluppatori, non sarà una questione di stile. Si tratterà di non comprendere le eccezioni in .NET e di pensare di dover catturare ogni eccezione, come in Java. Nella maggior parte dei casi, è meglio lasciar propagare l'eccezione. –

15

Nel contesto di un metodo che apre un file, utilizzerei un'istruzione using rispetto a un try catch. L'istruzione using garantisce che Dispose venga chiamato se si verifica un'eccezione.

using (FileStream fs = new FileStream(file, FileMode.Open)) 
{ 
    //do stuff 
} 

fa la stessa cosa:

FileStream fs; 
try 
{ 
    fs = new FileStream(file, FileMode.Open); 
    //do Stuff 
} 
finally 
{ 
     if(fs!=null) 
      fs.Dispose(); 
} 
+3

Chiudi, ma il codice try/finally non corrisponde esattamente al codice utilizzato. Devi anche avvolgerlo in un blocco anonimo. –

1

maggior parte del tempo mi rompere i blocchi try/catch annidati in funzioni. Ma a volte ho scritto codice per catturare e registrare tutte le eccezioni non rilevate generate dalla mia applicazione. Ma cosa succede se il codice di registrazione fallisce? Quindi ho ancora un altro tentativo/aggirare questo solo per impedire all'utente di vedere la finestra di dialogo di eccezione non gestita. NET predefinito. Ma anche questo codice potrebbe essere facilmente refactored in funzioni invece di blocchi try/catch nidificati.

try 
{ 
    try 
    { 
     DoEverything(); 
    } 
    catch (Exception ex) 
    { 
     // Log the exception here 
    } 
} 
catch (Exception ex) 
{ 
    // Wow, even the log is broken ... 
} 
+1

Se la registrazione è interrotta, è necessario consentire l'propagazione dell'eccezione in modo che l'utente possa lamentarsi del fatto che la registrazione è interrotta! –

+0

Posso ancora mostrare l'eccezione generata dal codice di registrazione. È solo che * I * vuole farlo invece di lasciare che la finestra di errore del framework si presenti. –

+0

qualsiasi modello di esempio valido utilizzando l'azione ? – Kiquenet

11

Ora che abbiamo lambda e di inferenza e alcune altre cose, c'è un idioma che è comune in altre lingue che ora fa un sacco di senso in C#. Il tuo esempio riguardava l'apertura di un file, l'esecuzione di qualcosa e la sua chiusura. Bene, ora puoi creare un metodo di supporto che apra un file e si occupi anche di assicurarti di chiudere/smaltire/ripulire, ma invoca un lambda che fornisci per la parte "fai da te". Ciò ti aiuterà a ottenere le complicate operazioni di try/catch/finally dispose/cleanup direttamente in un unico posto, e quindi a utilizzarle più e più volte.

Ecco un esempio:

public static void ProcessFile(string filePath, Action<File> fileProcessor) 
{ 
    File openFile = null; 

    try 
    { 
    openFile = File.Open(filePath); // I'm making this up ... point is you are acquiring a resource that needs to be cleaned up after. 

    fileProcessor(openFile); 
    } 
    finally 
    { 
    openFile.Close(); // Or dispose, or whatever. 
    } 
} 

Ora, i chiamanti di questo metodo non c'è bisogno di preoccuparsi di come aprire il file o chiudere/smaltirlo. Possono fare qualcosa di simile a questo:

Helpers.ProcessFile("C://somefile.txt", f => 
{ 
    while(var text = f.ReadLine()) 
    { 
    Console.WriteLine(text); 
    } 
}); 
+0

posso inserire il codice "while" in un metodo di un'altra classe? – Kiquenet

+0

@alhambraeidos, se sto capendo correttamente, sì, assolutamente possibile. Potresti creare un metodo chiamato "ForEachLine", che apre il file, esegue un ciclo while per leggerlo riga per riga e chiama la funzione che inserisci su ogni riga. –

+0

In questo modo: MyHelperClass4Files.ForEachLine (f); ?? – Kiquenet

3

Come su dove si dispone di codice correlato che non appartiene necessariamente in una funzione separata del proprio diritto? Questo sarebbe quindi corretto?

try 
{ 
    // Part 1 Code Here 

    try 
    { 
    // Part 2 Code Here 
    } 
    catch (Exception ex) 
    { 
    // Error from Part 2 
    } 
} 
catch (Exception ex) 
{ 
    // Error from Part 1 
} 
-2
try 
{ 
    ---- 
} 
catch 
{ 
    try 
     { 
      --- 
     } 
    catch 
     { 
     --- 
     } 
} 
+0

Perché è stato assegnato un voto negativo? –

0
//create a switch here and set it to 0 
try 
{ 
    DoChunk1(); 
    //looks good. set the switch to 1 
} 
catch (Exception ex) 
{ 
    // Log the exception here 
} 

// controlla l'interruttore, se è ancora pari a zero, a questo punto allora si può fermare il programma qui; altrimenti resetta lo switch a zero ed esegui la tua successiva dichiarazione catch. totalmente d'accordo con la loro rottura come menzionato sopra

provare { DoChunk2(); // sembra buono. impostare l'interruttore 1 } catch (Exception ex) { // Log eccezione qui }