2009-11-12 7 views
26

Ho letto e capisco cosa fa un blocco Try/Catch e perché è importante usarne uno. Ma sono bloccato a sapere quando/dove usarli. Qualche consiglio? Inserirò un esempio del mio codice qui sotto nella speranza che qualcuno abbia del tempo per formulare alcune raccomandazioni per il mio esempio.Quando utilizzare i blocchi try/catch?

public AMPFileEntity(string filename) 
    { 
     transferFileList tfl = new transferFileList(); 
     _AMPFlag = tfl.isAMPFile(filename); 
     _requiresPGP = tfl.pgpRequired(filename); 
     _filename = filename.ToUpper(); 
     _fullSourcePathAndFilename = ConfigurationSettings.AppSettings.Get("sourcePath") + _filename; 
     _fullDestinationPathAndFilename = ConfigurationSettings.AppSettings.Get("FTPStagePath") + _filename; 
     _hasBeenPGPdPathAndFilename = ConfigurationSettings.AppSettings.Get("originalsWhichHaveBeenPGPdPath"); 
    } 


    public int processFile() 
    { 

     StringBuilder sb = new StringBuilder(); 
     sb.AppendLine(" "); 
     sb.AppendLine(" --------------------------------"); 
     sb.AppendLine("  Filename: " + _filename); 
     sb.AppendLine("  AMPFlag: " + _AMPFlag); 
     sb.AppendLine("  Requires PGP: " + _requiresPGP); 
     sb.AppendLine(" --------------------------------"); 
     sb.AppendLine(" "); 

     string str = sb.ToString(); 
     UtilityLogger.LogToFile(str); 
     if (_AMPFlag) 
     { 
      if (_requiresPGP == true) 
      { 
       encryptFile(); 
      } 
      else 
      { 
       UtilityLogger.LogToFile("This file does not require encryption. Moving file to FTPStage directory."); 
       if (File.Exists(_fullDestinationPathAndFilename)) 
       { 
        UtilityLogger.LogToFile(_fullDestinationPathAndFilename + " alreadyexists. Archiving that file."); 
        if (File.Exists(_fullDestinationPathAndFilename + "_archive")) 
        { 
         UtilityLogger.LogToFile(_fullDestinationPathAndFilename + "_archive already exists. Overwriting it."); 
         File.Delete(_fullDestinationPathAndFilename + "_archive"); 
        } 
        File.Move(_fullDestinationPathAndFilename, _fullDestinationPathAndFilename + "_archive"); 
       } 
       File.Move(_fullSourcePathAndFilename, _fullDestinationPathAndFilename); 
      } 
     } 
     else 
     { 
      UtilityLogger.LogToFile("This file is not an AMP transfer file. Skipping this file."); 
     } 

      return (0); 
    } 


    private int encryptFile() 
    { 

     UtilityLogger.LogToFile("This file requires encryption. Starting encryption process."); 


     // first check for an existing PGPd file in the destination dir. if exists, archive it - otherwise this one won't save. it doesn't overwrite. 
     string pgpdFilename = _fullDestinationPathAndFilename + ".PGP"; 



     if(File.Exists(pgpdFilename)) 
     { 
      UtilityLogger.LogToFile(pgpdFilename + " already exists in the FTPStage directory. Archiving that file."); 
      if(File.Exists(pgpdFilename + "_archive")) 
      { 
       UtilityLogger.LogToFile(pgpdFilename + "_archive already exists. Overwriting it."); 
       File.Delete(pgpdFilename + "_archive"); 
      } 
      File.Move(pgpdFilename, pgpdFilename + "_archive"); 
     } 

     Process pProc = new Process(); 
     pProc.StartInfo.FileName = "pgp.exe"; 

     string strParams = @"--encrypt " + _fullSourcePathAndFilename + " --recipient infinata --output " + _fullDestinationPathAndFilename + ".PGP"; 

     UtilityLogger.LogToFile("Encrypting file. Params: " + strParams); 
     pProc.StartInfo.Arguments = strParams; 
     pProc.StartInfo.UseShellExecute = false; 
     pProc.StartInfo.RedirectStandardOutput = true; 
     pProc.Start(); 
     pProc.WaitForExit(); 

     //now that it's been PGPd, save the orig in 'hasBeenPGPd' dir 
     UtilityLogger.LogToFile("PGP encryption complete. Moving original unencrypted file to " + _hasBeenPGPdPathAndFilename); 
     if(File.Exists(_hasBeenPGPdPathAndFilename + _filename + "original_which_has_been_pgpd")) 
     { 
      UtilityLogger.LogToFile(_hasBeenPGPdPathAndFilename + _filename + "original_which_has_been_pgpd already exists. Overwriting it."); 
      File.Delete(_hasBeenPGPdPathAndFilename + _filename + "original_which_has_been_pgpd"); 
     } 
      File.Move(_fullSourcePathAndFilename, _hasBeenPGPdPathAndFilename + _filename + "original_which_has_been_pgpd"); 

     return (0); 

    } 
} 

}

+2

Cerca qui 'try catch C#': http://stackoverflow.com/questions/523875/where-to-put-try-catch http://stackoverflow.com/questions/751744/thoughts-on- try-catch-blocks http://stackoverflow.com/questions/505471/how-often-should-i-use-and-catch-in-c e quindi no ... – Lazarus

+0

Ci sono tonnellate di domande sulla gestione delle eccezioni su questo sito! –

+0

So che ci sono un milione di posti in cui ho potuto leggere sulla gestione delle eccezioni. Infatti ho menzionato nel mio post che ho capito il concetto. Sono bloccato all'attuazione in questo momento e lo scopo del mio post era sperare che qualcuno mi mostrasse come applicarlo alla mia particolare circostanza, il mio esempio di codice specifico. – fieldingmellish

risposta

58

La regola di base del pollice per le eccezioni cattura è di eccezioni cattura se e solo se avete un modo significativo di loro manipolazione.

Do not rilevare un'eccezione se si intende solo registrare l'eccezione e rilasciarla nello stack. Non serve alcun significato e codice di clutter.

Do È possibile rilevare un'eccezione quando si prevede un errore in una parte specifica del codice e se si dispone di un fallback per esso.

Ovviamente si ha sempre il caso di eccezioni controllate che richiedono l'utilizzo di blocchi try/catch, nel qual caso non si ha altra scelta. Anche con un'eccezione controllata, assicurati di accedere correttamente e gestisci il più pulito possibile.

+1

Secondo me, registrare tutte le eccezioni è una buona idea, a patto che tu lo faccia in alto nello stack delle chiamate e aggiunga un "throw"; dichiarazione subito dopo. – Manu

+0

@Manu: non è sempre la strada da percorrere. Immagina di essere un amministratore di sistema e apri un file di registro solo per trovare centinaia di tracce inutili che dicono tutte "eccezione in XXX". Questo ha un grande impatto sul TCO e solitamente non ha alcun beneficio. Accedi al posto più appropriato in modo che un amministratore di sistema abbia una traccia significativa con cui lavorare. –

+1

IIS tiene traccia di tutte le eccezioni generate e ci sono molte soluzioni (ad esempio ELMAH) che registreranno tutte le eccezioni senza ingombrare il codice. –

2

Mi è stato insegnato a utilizzare try/catch/finally per tutti i metodi/classi in cui potrebbero verificarsi più errori e che è possibile gestire effettivamente. Transazioni di database, I/O FileSystem, streaming, ecc. La logica di base di solito non richiede try/catch/finally.

La gran parte di try/catch/finally è che si può avere più catture in modo da poter creare una serie di gestori di eccezioni a che fare con errore molto specifico o utilizzare una deroga generale per catturare gli errori che si don' vedo arrivare.

Nel tuo caso, stai utilizzando File.Exists che è buono, ma forse è un altro problema con il disco che potrebbe generare un altro errore che File.Exists non è in grado di gestire. Sì, è un metodo booleano, ma dì che il File è bloccato e cosa succede se provi a scrivere su di esso? Con la cattura, puoi pianificare uno scenario raro, ma senza try/catch/finally, potresti esporre il codice a condizioni completamente impreviste.

+0

Alcune delle affermazioni riportate qui non sono vere: è sempre utile tentare di rilevare eccezioni per FileIO, ad esempio: consente allo sviluppatore di notificare all'utente che, ad esempio, potrebbe non esserci spazio sufficiente sull'unità richiesta per completare l'operazione di salvataggio, o il file non esiste (se il dev non ha codificato i controlli correttamente ... purtroppo che ho * visto *). – Paul

+0

@Paul se è possibile codificarlo come eccezione, è anche possibile codificarlo come requisito all'inizio della funzione. Quindi la domanda non è tanto se si devono usare le eccezioni, ma se non c'è altra alternativa. Eccezioni non sempre rendono il codice più pulito, dal momento che stai spostando la parte di gestione dall'errore. –

1

Gli altri ragazzi hanno dato un buon numero di buoni suggerimenti e riferimenti.

Il mio input è breve:
Quando usarlo è una cosa, in modo uguale o più importante è come usarlo correttamente.

PS: "it" è refeings a "try-catching exceptions".

+0

Non potrei essere più d'accordo. – Paul

1

Come altri hanno già detto, si desidera utilizzare il blocco di prova attorno al codice che può generare un'eccezione E che si è pronti a gestire.

Per alcuni esempi, File.Delete può generare numerose eccezioni, tra cui IOException, UnauthorizedAccessException e altre. Cosa vorresti che la tua applicazione facesse in quelle situazioni? Se provi a eliminare il file ma qualcuno da qualche altra parte lo sta usando, otterrai una IOException.

try 
    {  
     File.Delete(pgpdFilename + "_archive") 
    } 
    catch(IOException) 
    { 
     UtilityLogger.LogToFile("File is in use, could not overwrite."); 
     //do something else meaningful to your application 
     //perhaps save it under a different name or something 
    } 

Anche tenere a mente che se questo fallisce, allora la File.Move si fare fuori il tuo blocco if prossima sarà anche fallire (di nuovo per un'IOException - dal momento che il file non è stato eliminato è ancora lì che causerà lo spostamento fallire).

Problemi correlati