Perché catturare e riproporre un'eccezione in C #?


557

Sto guardando l'articolo C # - Data Transfer Object su DTO serializzabili.

L'articolo include questo pezzo di codice:

public static string SerializeDTO(DTO dto) {
    try {
        XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
        StringWriter sWriter = new StringWriter();
        xmlSer.Serialize(sWriter, dto);
        return sWriter.ToString();
    }
    catch(Exception ex) {
        throw ex;
    }
}

Il resto dell'articolo sembra sano e ragionevole (a un noob), ma quel tentativo-catch-throw genera un'eccezione Wtf ... Non è esattamente equivalente a non gestire affatto le eccezioni?

Quindi:

public static string SerializeDTO(DTO dto) {
    XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
    StringWriter sWriter = new StringWriter();
    xmlSer.Serialize(sWriter, dto);
    return sWriter.ToString();
}

O mi sto perdendo qualcosa di fondamentale sulla gestione degli errori in C #? È praticamente lo stesso di Java (meno le eccezioni controllate), non è vero? ... Cioè, hanno entrambi perfezionato C ++.

La domanda Stack Overflow La differenza tra rilanciare la cattura senza parametri e non fare nulla? sembra supportare la mia tesi secondo cui provare a catturare è un no-op.


MODIFICARE:

Riassumendo per chiunque trovi questa discussione in futuro ...

NON

try {
    // Do stuff that might throw an exception
}
catch (Exception e) {
    throw e; // This destroys the strack trace information!
}

Le informazioni sulla traccia dello stack possono essere cruciali per identificare la causa principale del problema!

FARE

try {
    // Do stuff that might throw an exception
}
catch (SqlException e) {
    // Log it
    if (e.ErrorCode != NO_ROW_ERROR) { // filter out NoDataFound.
        // Do special cleanup, like maybe closing the "dirty" database connection.
        throw; // This preserves the stack trace
    }
}
catch (IOException e) {
    // Log it
    throw;
}
catch (Exception e) {
    // Log it
    throw new DAOException("Excrement occurred", e); // wrapped & chained exceptions (just like java).
}
finally {
    // Normal clean goes here (like closing open files).
}

Cattura le eccezioni più specifiche prima di quelle meno specifiche (proprio come Java).


Riferimenti:


8
Buon riassunto; punti extra per l'inclusione del blocco finally.
Fredrik Mörk,

vorrei aggiungere che è possibile utilizzare il "lancio;" per essere ancora più utile aggiungendo i parametri che sono stati inviati al metodo nella raccolta e.Data prima del "lancio;" dichiarazione
Michael Bahig,

@MickTheWarMachineDesigner (e pittore part-time). Eh? Stai parlando di gestire le eccezioni di Microshite Suckwell (probabilmente dal 2005 in poi, per quanto ne so). Stavo parlando della gestione delle eccezioni in generale. E sì, ne ho imparato un po 'da quando ho pubblicato QUESTO QUATTRO ANNI ANCORA .... Ma sì, confesso che hai un punto valido, ma io penso che tu abbia perso il punto vero; Se capisci cosa intendo? Questa domanda riguarda la gestione delle eccezioni GENERALIZZATA in C #; e più specificamente riguardo al rinnovo delle eccezioni ... di TUTTI i tipi. Freddo?
corlettk,

Ti preghiamo di considerare di spostare la sezione di riepilogo della modifica nella tua domanda nella sua risposta. Per il motivo, vedere Modifica della risposta automatica fuori domanda e Risposta incorporata nella domanda .
DavidRR

2
Qualcuno non ha notato la parte "Si sono verificati degli escrementi"? sembra che il codice sia andato per una cacca!
Jason Loki Smith il

Risposte:


430

Primo; il modo in cui il codice dell'articolo lo fa è malvagio. throw exreimposterà lo stack di chiamate nell'eccezione al punto in cui si trova questa istruzione di lancio; perdere le informazioni su dove l'eccezione è stata effettivamente creata.

In secondo luogo, se catturi e rilasci in questo modo, non vedo alcun valore aggiunto, l'esempio di codice sopra sarebbe altrettanto buono (o, dato il throw exbit, anche migliore) senza il try-catch.

Tuttavia, ci sono casi in cui potresti voler catturare e riproporre un'eccezione. La registrazione potrebbe essere una di queste:

try 
{
    // code that may throw exceptions    
}
catch(Exception ex) 
{
    // add error logging here
    throw;
}

6
@Fredrick, solo fyi (anche se probabilmente lo sai) se non hai intenzione di utilizzare exquell'oggetto, non è necessario crearne un'istanza.
Eoin Campbell,

78
@Eoin: se non è istanziato, sarebbe piuttosto difficile registrarlo.
Sam Axe

30
Sì, penso che "male" sia giusto ... considera il caso dell'eccezione puntatore nullo generata da qualche parte di codice. Il messaggio è vaniglia, senza la traccia dello stack ti rimane "qualcosa era nullo da qualche parte". NON buono quando la produzione è morta; e non hai NESSUN minuto o meno per risolvere il problema di Flamin e liquidarlo o correggerlo ... Una buona gestione delle eccezioni vale il suo peso in oro.
corlettk,

4
È vero anche per Java ... "lanciare" contro "lanciare ex"?
JasonStoltz,

8
@Jason, vedi questa domanda . In Java, throw exnon riavvia lo stacktrace.
Matthew Flaschen,

117

Non farlo

try 
{
...
}
catch(Exception ex)
{
   throw ex;
}

Perderai le informazioni sulla traccia dello stack ...

O fare

try { ... }
catch { throw; }

O

try { ... }
catch (Exception ex)
{
    throw new Exception("My Custom Error Message", ex);
}

Uno dei motivi per cui potresti voler ripensare è se stai gestendo diverse eccezioni, ad esempio

try
{
   ...
}
catch(SQLException sex)
{
   //Do Custom Logging 
   //Don't throw exception - swallow it here
}
catch(OtherException oex)
{
   //Do something else
   throw new WrappedException("Other Exception occured");
}
catch
{
   System.Diagnostics.Debug.WriteLine("Eeep! an error, not to worry, will be handled higher up the call stack");
   throw; //Chuck everything else back up the stack
}

7
Perché non lasciare semplicemente catch {throw}?
AnthonyWJones,

3
c'è ancora valore nel lasciare la cattura {lancio; } in fondo a un elenco di specifici tipi di eccezione catturati per il fatto che l'autore ha considerato il caso, anche se un commento potrebbe ugualmente bastare. Non indovinare quando leggi il codice è una buona cosa.
annakata,

87
Per qualche ragione, il nome di SQLException mi dà fastidio.
Michael Myers

13
Quella cattura (Eccezione) {lanciare nuova Eccezione (...)} è qualcosa che non dovresti mai, mai e poi mai , semplicemente perché stai offuscando le informazioni sull'eccezione e rendendo inutilmente difficile il filtraggio delle eccezioni nello stack di chiamate. L'unica volta che dovresti prendere un tipo di eccezione e lanciarne un altro è quando stai implementando un livello di astrazione e devi trasformare un tipo di eccezione specifico del provider (ad esempio SqlException contro XmlException) in uno più generico (ad esempio DataLoadingException).
Jammycakes,

3
@dark_perfect dovresti controllare l'argomento in anticipo, all'inizio del metodo e lanciare ArgumentNullException lì (errore veloce).
Andrei Bozantan,

56

C # (prima di C # 6) non supporta le "eccezioni filtrate" di CIL, cosa che fa VB, quindi in C # 1-5 un motivo per rilanciare un'eccezione è che non hai abbastanza informazioni al momento della cattura () per determinare se si desidera catturare effettivamente l'eccezione.

Ad esempio, in VB puoi farlo

Try
 ..
Catch Ex As MyException When Ex.ErrorCode = 123
 .. 
End Try

... che non gestirà MyExceptions con valori ErrorCode diversi. In C # prima della v6, dovresti catturare e rilanciare MyException se ErrorCode non fosse 123:

try 
{
   ...
}
catch(MyException ex)
{
    if (ex.ErrorCode != 123) throw;
    ...
}

Da C # 6.0 puoi filtrare proprio come con VB:

try 
{
  // Do stuff
} 
catch (Exception e) when (e.ErrorCode == 123456) // filter
{
  // Handle, other exceptions will be left alone and bubble up
}

2
Dave, ma (almeno in Java) non lanceresti una MyException "generica", definiresti un tipo di eccezione SPECIFIC e lo lanci, permettendogli di differenziarsi per tipo nel blocco catch ... Ma sì , se non sei l'architetto dell'eccezione (sto pensando a SQLException di JDBC (di nuovo Java) qui, che è disgustosamente generico ed espone il metodo getErrorCode () ... Hmmm ... Hai un punto, è solo che Penso che ci sia un modo migliore per farlo, ove possibile. Saluti Mate, apprezzo molto il tuo tempo, Keith.
Corlettk,

1
Bene, la domanda è "Perché catturare e rilanciare l'eccezione in C #?", E questa è una risposta. =] ... e anche con eccezioni specializzate, i filtri delle eccezioni hanno senso: considera il caso in cui ti trovi, diciamo, a gestire SqlTimeoutException e SqlConnectionResetException, che sono entrambi SqlException. I filtri di eccezione ti consentono di catturare una SqlException solo quando è una di queste due, quindi invece di ingombrare il tuo try / catch con la stessa gestione per questi due, potresti "catturare SqlException ex quando ex è SqlTimeoutException o ex è SqlConnectionResetException". (Non sono Dave a proposito)
bzlm

3
Le eccezioni filtrate stanno arrivando in C # 6!
Sir Crispalot,

14

Il mio motivo principale per avere un codice come:

try
{
    //Some code
}
catch (Exception e)
{
    throw;
}

è così che posso avere un punto di interruzione nel fermo, che ha un oggetto eccezione istanziato. Lo faccio molto durante lo sviluppo / debug. Naturalmente, il compilatore mi dà un avvertimento su tutte le e inutilizzate, e idealmente dovrebbero essere rimosse prima di una build di rilascio.

Sono comunque simpatici durante il debug.


1
Sì, pagherò quello, ma sì, non vorrai vederlo nel codice pubblicato ... ergo: mi vergognerei di pubblicarlo ;-)
corlettk,

25
In realtà, questo non è necessario: in Visual Studio è possibile impostare il debugger affinché si interrompa quando viene generata un'eccezione e vengono visualizzati i dettagli dell'eccezione in una finestra di ispezione.
Jammycakes,

8
Se si desidera utilizzare del codice SOLO durante il debug, utilizzare #if DEBUG ... #endif e non è necessario rimuovere queste righe
Michael Freidgeim,

1
Ya, l'ho fatto alcune volte da solo. Di tanto in tanto si scappa a un rilascio. @jammycakes Il problema con l'interruzione di Visual Studio in caso di eccezione è, a volte l'eccezione che desidero non è l'unica (o anche solo una del suo tipo) ad essere lanciata. Ancora non conosco una condizione del punto di interruzione con "break se ignorato dall'eccezione". Fino ad allora, questo rimarrà utile. Michael Freidgeim: in #if DEBUGgiro ENTRAMBI l'uno try {ed } catch () {...}è un po 'disordinato e, francamente, mi fa sentire nauseato ... Il pre-processore, in generale, non è mio amico.

11

Un motivo valido per riproporre le eccezioni può essere che si desidera aggiungere informazioni all'eccezione, o magari racchiudere l'eccezione originale in uno di propria creazione:

public static string SerializeDTO(DTO dto) {
  try {
      XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
      StringWriter sWriter = new StringWriter();
      xmlSer.Serialize(sWriter, dto);
      return sWriter.ToString();
  }
  catch(Exception ex) {
    string message = 
      String.Format("Something went wrong serializing DTO {0}", DTO);
    throw new MyLibraryException(message, ex);
  }
}

Grazie, sì, il wrapping delle eccezioni (specialmente incatenato) è perfettamente sano ... ciò che non è sano è catturare un'eccezione solo in modo da poter eliminare la traccia dello stack, o peggio, mangiarla.
corlettk,

10

Non è esattamente equivalente a non gestire affatto le eccezioni?

Non esattamente, non è lo stesso. Reimposta lo stacktrace dell'eccezione. Anche se concordo sul fatto che questo probabilmente è un errore, e quindi un esempio di codice errato.


8

Non vuoi lanciare ex - poiché questo perderà lo stack di chiamate. Vedi Gestione delle eccezioni (MSDN).

E sì, il tentativo ... catch non sta facendo nulla di utile (a parte perdere lo stack di chiamate - quindi in realtà è peggio - a meno che per qualche motivo non volessi esporre queste informazioni).


Non si perde l'intero stack di chiamate quando si utilizza il lancio ex, si perde solo la parte dello stack di chiamate dal punto in cui si è verificata l'eccezione più in alto nel relativo stack. Ma mantieni lo stack di chiamate dal metodo che ha gettato l'eccezione nel punto in cui il client l'ha chiamato. In realtà potrebbero esserci casi d'uso in cui lo useresti, altrimenti le brave persone di Microsoft non lo avrebbero permesso. Detto questo, non l'ho usato. Un altro problema da ricordare è che generare eccezioni è costoso. Fallo solo per un motivo molto giustificabile. Registrazione che riterrei giustificabile, ecc.
Charles Owen,

5

Un punto che la gente non ha menzionato è che mentre i linguaggi .NET non fanno una vera distinzione, la questione se si debba agire quando si verifica un'eccezione e se si risolverà , in realtà sono domande distinte. Ci sono molti casi in cui si dovrebbe agire in base a eccezioni che non si hanno speranze di risolvere, e ci sono alcuni casi in cui tutto ciò che è necessario per "risolvere" un'eccezione è di svolgere lo stack fino a un certo punto - non sono necessarie ulteriori azioni .

A causa della saggezza comune secondo cui si dovrebbero solo "catturare" le cose che si possono "gestire", un sacco di codice che dovrebbe agire in caso di eccezioni, non lo fa. Ad esempio, un sacco di codice acquisirà un lucchetto, metterà l'oggetto protetto "temporaneamente" in uno stato che viola i suoi invarianti, quindi rimetterà l'oggetto in uno stato legittimo, quindi rilascerà il lucchetto prima che chiunque possa vedere l'oggetto. Se si verifica un'eccezione mentre l'oggetto si trova in uno stato pericolosamente non valido, la pratica comune è rilasciare il blocco con l'oggetto ancora in quello stato. Un modello molto migliore sarebbe quello di avere un'eccezione che si verifica mentre l'oggetto si trova in una condizione "pericolosa" invalidando espressamente il blocco, quindi qualsiasi tentativo futuro di acquisirlo fallirà immediatamente.

Nella maggior parte dei linguaggi .NET, l'unico modo per il codice di agire in base a un'eccezione è catchfarlo (anche se sa che non risolverà l'eccezione), eseguire l'azione in questione e quindi ri- throw). Un altro possibile approccio se al codice non interessa quale eccezione viene generata è l'uso di un okflag con un try/finallyblocco; imposta il okflag su falseprima del blocco e trueprima che il blocco esca e prima di qualsiasi returncosa si trovi all'interno del blocco. Quindi, all'interno finally, supponi che se oknon è impostato, deve essersi verificata un'eccezione. Tale approccio è semanticamente migliore di un catch/ throw, ma è brutto ed è meno mantenibile di quanto dovrebbe essere.


5

Questo può essere utile quando la tua programmazione funziona per una libreria o dll.

Questa struttura di ricodificazione può essere utilizzata per ripristinare intenzionalmente lo stack di chiamate in modo che invece di vedere l'eccezione generata da una singola funzione all'interno della funzione, si ottenga l'eccezione dalla funzione stessa.

Penso che questo sia solo usato in modo che le eccezioni generate siano più pulite e non vadano nelle "radici" della biblioteca.


3

Un possibile motivo per intercettare è disabilitare qualsiasi filtro delle eccezioni più approfondito dal filtraggio verso il basso ( vecchio collegamento casuale ). Ma ovviamente, se questa fosse l'intenzione, ci sarebbe un commento lì a dirlo.


Non ho capito di cosa ti occupassi finché non ho letto il link ... e non sono ancora esattamente sicuro di cosa tu stia facendo ... non ho familiarità con VB.NET. Penso che risulti che la somma viene segnalata come "incoerente", giusto? ... Sono un GRANDE fan dei metodi statici ... a parte il fatto che sono semplici, ci sono meno possibilità di incoerenza se si separa l'impostazione degli attributi dal codice che fa il vero lavoro. Lo stack è "autopulente".
corlettk,

3
Le persone si aspettano che quando scrivono "prova {Foo ();} finalmente {Bar ();}" che non ci sia nulla tra Foo e Bar. Ma questo non è vero; se il tuo chiamante ha aggiunto un filtro delle eccezioni e non ci sono 'catture' intermedie, e Foo () lancia, allora qualche altro codice casuale dal tuo chiamante verrà eseguito prima dell'esecuzione di (Bar). Questo è molto brutto se hai infranto gli invarianti o hai elevato la sicurezza, aspettandoti che saranno "immediatamente" ripristinati alla normalità da finalmente e nessun altro codice vedrà il cambiamento temporaneo.
Brian,

3

Dipende da cosa stai facendo nel blocco catch e se vuoi passare l'errore al codice chiamante oppure no.

Si potrebbe dire Catch io.FileNotFoundExeption exe quindi utilizzare un percorso di file alternativo o alcuni di questi, ma ancora generare l'errore.

Anche fare Throwinvece di Throw Exconsente di mantenere la traccia dello stack completo. Throw ex riavvia la traccia dello stack dall'istruzione throw (spero che abbia senso).


3

Mentre molte delle altre risposte forniscono buoni esempi del motivo per cui potresti voler cogliere un'eccezione di ripensamento, nessuno sembra aver menzionato uno scenario "finalmente".

Un esempio di ciò è dove hai un metodo in cui imposti il ​​cursore (ad esempio un cursore di attesa), il metodo ha diversi punti di uscita (ad es. If () return;) e vuoi assicurarti che il cursore sia resettato fine del metodo.

Per fare ciò è possibile racchiudere tutto il codice in un tentativo / catch / infine. In infine imposta il cursore sul cursore destro. In modo da non seppellire alcuna valida eccezione, riprovare a catturare.

try
{
    Cursor.Current = Cursors.WaitCursor;
    // Test something
    if (testResult) return;
    // Do something else
}
catch
{
    throw;
}
finally
{
     Cursor.Current = Cursors.Default;
}

1
Storicamente è stata catchuna parte obbligatoria try...finallyo gioca un ruolo funzionale in questo esempio? - Ho appena ricontrollato e sono in grado di utilizzare try {} finally {}senza il blocco catch.
Sebi,

2

Nell'esempio nel codice che hai pubblicato, infatti, non ha senso catturare l'eccezione in quanto non viene fatto nulla sulla cattura che viene semplicemente riproposta, infatti fa più male che bene quando si perde lo stack di chiamate .

Tuttavia, dovresti rilevare un'eccezione per fare un po 'di logica (ad esempio chiudendo la connessione sql del blocco dei file, o solo un po' di registrazione) in caso di un'eccezione, riportandola al codice chiamante per gestire. Ciò sarebbe più comune in un livello aziendale rispetto al codice front-end, poiché è possibile che il programmatore che implementa il livello aziendale gestisca l'eccezione.

Per ripetere l'iterazione, sebbene non vi sia alcun punto nel catturare l'eccezione nell'esempio che hai pubblicato. NON farlo così!


1

Siamo spiacenti, ma molti esempi di "design migliorato" hanno ancora un odore orribile o possono essere estremamente fuorvianti. Avere provato {} catch {log; throw} è assolutamente inutile. La registrazione delle eccezioni deve essere eseguita in posizione centrale all'interno dell'applicazione. le eccezioni riempiono comunque lo stacktrace, perché non registrarli da qualche parte in alto e vicino ai bordi del sistema?

Si deve usare cautela quando si serializza il contesto (ad es. DTO in un dato esempio) solo nel messaggio di registro. Può facilmente contenere informazioni riservate che non si potrebbe desiderare di raggiungere le mani di tutte le persone che possono accedere ai file di registro. E se non aggiungi nuove informazioni all'eccezione, in realtà non vedo il punto del wrapping dell'eccezione. Il buon vecchio Java ha qualche punto a riguardo, richiede che il chiamante sappia che tipo di eccezioni ci si dovrebbe aspettare quindi chiamare il codice. Dal momento che non hai questo in .NET, il wrapping non fa nulla di buono su almeno l'80% dei casi che ho visto.


Grazie per il tuo pensiero Joe. In Java (e C #, suppongo) mi piacerebbe vedere un'annotazione a livello di classe @FaultBoundary che impone che TUTTE le eccezioni (inclusi i tipi di eccezione non controllati) vengano catturate o dichiarate da lanciare. Vorrei usare questa annotazione su interfacce pubbliche di ogni livello architettonico. Pertanto l'interfaccia @FaultBoundary ThingDAO non sarebbe in grado di svelare dettagli di implementazione come SQLExceptions, NPE o AIOB. Invece lo stacktrace "causale" verrebbe registrato e verrebbe lanciata una DAOSystemException ... Definisco l'eccezione di sistema come "permanentemente fatale".
corlettk,

5
Ci sono molte ragioni per catturare, registrare, quindi riprovare. In particolare se il metodo con il registro delle catture contiene informazioni che perdi una volta uscito dal metodo. L'errore può essere gestito in seguito ma non registrato e hai perso informazioni sui difetti nel sistema.
Andy,

1
Qui è utile la proprietà Data della classe Exception: acquisire tutte le informazioni locali per la registrazione generica. Questo articolo lo ha originariamente portato alla mia attenzione: blog.abodit.com/2010/03/…
McGuireV10

1

Oltre a ciò che hanno detto gli altri, vedi la mia risposta a una domanda correlata che mostra che catturare e ricrescere non è una no-op (è in VB, ma parte del codice potrebbe essere invocato in C # da VB).


Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il collegamento come riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - Dalla recensione
LHIOUI,

@HamzaLH, sono d'accordo che non è una risposta ben scritta, ma ha informazioni, diverse da altre risposte e voti positivi. Quindi non capisco, perché suggerisci di eliminarlo? "Le risposte brevi che sono in argomento e danno una soluzione sono ancora risposte." Da meta.stackexchange.com/questions/226258/…
Michael Freidgeim,

questa è una risposta solo link
LHIOUI

1. Le risposte di solo collegamento devono essere modificate in commenti, non eliminate. 2. È un riferimento ad un'altra domanda SO, non a un sito esterno, che ha ritenuto meno probabile di essere rotto nel tempo. 3. Ha una descrizione in più, che lo rende non "solo link" - vedi meta.stackexchange.com/questions/225370/…
Michael Freidgeim

1

La maggior parte delle risposte parla di scenari catch-log-rethrow.

Invece di scriverlo nel tuo codice, considera di utilizzare AOP, in particolare Postsharp.Diagnostic.Toolkit con OnExceptionOptions IncludeParameterValue e IncludeThisArgument


Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il collegamento come riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - Dalla recensione
Tony Dong,

@TonyDong, sono d'accordo che non è una risposta ben scritta, ma ha informazioni, diverse da altre risposte e voti positivi. Quindi non capisco, perché suggerisci di eliminarlo? A proposito, il collegamento 5 anni dopo è ancora valido. "Le risposte brevi che sono in argomento e danno una soluzione sono ancora risposte." Da meta.stackexchange.com/questions/226258/…
Michael Freidgeim,

Stackoverflow ha solo questo suggerimento.
Tony Dong,

@TonyDong, se la risposta non è assolutamente inutile, dovresti scegliere “Sembra OK”
Michael Freidgeim,

0

Riscoprire le eccezioni via throw è utile quando non si dispone di un codice specifico per gestire le eccezioni correnti o nei casi in cui si dispone di una logica per gestire casi di errore specifici ma si desidera ignorare tutti gli altri.

Esempio:

string numberText = "";
try
{
    Console.Write("Enter an integer: ");
    numberText = Console.ReadLine();
    var result = int.Parse(numberText);

    Console.WriteLine("You entered {0}", result);
}
catch (FormatException)
{
    if (numberText.ToLowerInvariant() == "nothing")
    {
        Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
    }
    else
    {
        throw;
    }
}    
finally
{
    Console.WriteLine("Freed some resources.");
}
Console.ReadKey();

Tuttavia, esiste anche un altro modo per farlo, utilizzando clausole condizionali nei blocchi catch:

string numberText = "";
try
{
    Console.Write("Enter an integer: ");
    numberText = Console.ReadLine();
    var result = int.Parse(numberText);

    Console.WriteLine("You entered {0}", result);
}
catch (FormatException) when (numberText.ToLowerInvariant() == "nothing")
{
    Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
}    
finally
{
    Console.WriteLine("Freed some resources.");
}
Console.ReadKey();

Questo meccanismo è più efficiente del rilancio di un'eccezione poiché il runtime .NET non deve ricostruire l'oggetto eccezione prima di rilanciarlo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.