2009-03-02 8 views
10

Se ho un metodo che restituisce qualcosa, comeblocchi try-catch con il tipo di ritorno

public DataTable ReturnSomething() 
{ 
    try 
    { 
     //logic here 
    return ds.Tables[0]; 
    } 
    catch (Exception e) 
    { 
     ErrorString=e.Message; 
    } 
} 

Questo produce errore del compilatore, ovviamente, perché catch{} blocco non restituisce nulla.

Così quando ho metodi con valori di ritorno non uso blocco try-catch, che è una cattiva pratica. Se c'è un errore, vorrei impostare la stringa di errore su quell'errore. Ma poi ho bisogno anche di un valore di ritorno. Consigli?

+0

"Così quando ho metodi con valori di ritorno non uso blocco try-catch, che è una cattiva pratica." dice chi? La maggior parte dei metodi restituisce valori senza essere racchiusi nei blocchi di prova. –

+0

Picchiato di 20 secondi! Anzi, appoggia quello che stavo per dire; se c'è un'eccezione - A MENO CHE tu te lo aspetti e possa fare qualcosa di utile su di esso, lascia che bolla al chiamante. –

+2

Ingerire le eccezioni è il vero problema qui. –

risposta

27

Conservare il valore di ritorno in una variabile temporanea come questa:

public DataTable ReturnSomething() 
{ 
    DataTable returnValue = null; 

    try 
    { 
     //logic here 
     returnValue = ds.Tables[0]; 
    } 
    catch (Exception e) 
    { 
     ErrorString=e.Message; 
    } 

    return returnValue; 
} 
+0

semplice e fa il lavoro. –

+3

Come altri hanno notato, dovresti pensare a lanciare l'eccezione invece di impostare un ErrorString. Se vuoi un'eccezione con il tuo messaggio, devi lanciare una nuova eccezione, con l'eccezione originale come eccezione interna. lanciare una nuova ArgumentException ("My message", e); – Svish

+0

Sono d'accordo con Svish e altri; anche se ho tentato di rispondere alla tua domanda come chiesto, non penso che sia la soluzione migliore per il tuo problema. – Simon

14

È necessario aumentare/eliminare l'eccezione nel blocco catch e gestirla nel metodo di chiamata.

public void invokeFaultyCode() 
{ 
    try 
    { 
     DataTable dt = ReturnSomething(); 
    } 
    catch(Exception e) 
    { 
     // Print the error message, cleanup, whatever 
    }  
} 
public DataTable ReturnSomething() throws Exception 
{ 
    try 
    { 
     //logic here 
    return ds.Tables[0]; 
    } 
    catch (Exception e) 
    { 
     ErrorString=e.Message; 
     throw; 
    } 
} 

PS: Ci scusiamo per qualsiasi errore di sintassi, sono un po 'arrugginito su C#.

+1

Si consiglia di lanciare semplicemente come lancio e modificherà lo stack di eccezioni. –

+0

Buon punto che hai qui. –

+1

Giusto per notare; accodare 'getta' su un metodo è un concetto Java che non esiste in .NET. – Robula

3

Dipende dall'applicazione. È possibile restituire null, uno DataTable vuoto o ciò che è adatto in circostanze.

+0

Dipende interamente dalle circostanze. Dovresti sempre porre la domanda "che cosa significa se si verifica un'eccezione qui?" piuttosto che seguire la stessa pratica meccanica. Parte della ragione di avere un gestore di eccezioni è, beh, HANDLE l'eccezione. – plinth

5

Si dovrebbe eseguire il wrap del chiamante con un tentativo di cattura ... eventuali eccezioni che si verificano nella routine che viene chiamata salteranno al chiamante e si possono catturare lì.

Personalmente, penso che sia eccessivo avere un tentativo di cattura in questa routine come si dovrebbe avere il chiamante che gestisce l'eccezione.

Per il mio esempio, questo sarebbe codificato come segue ...

private void DoSomething() { 
    try { 
     DataTable dt = ReturnSomething(); 
    } 
    catch (Exception ex) { 
    }  
} 

public DataTable ReturnSomething() { 
    DataTable dt = new DataTable(); 

    // logic here 
    return dt; 
} 
0

penso che il codice viene eseguito in un livello sufficientemente alto dello stack di chiamate ed è combinato con il codice UI. Se questo è davvero il caso, è possibile inserire return null nel blocco catch. Tuttavia, se stai scrivendo un codice riusabile, dovresti rifattarlo in modo che non contenga la manipolazione dell'interfaccia utente e gestisca l'eccezione a un livello superiore nello stack di chiamate.

0

Dato che stai cacendo l'eccezione (e non rilanciandola) nel tuo esempio, il codice esterno presuppone che tutto sia a posto e che tu debba restituire qualcosa di utile.

Se è necessario rilevare l'eccezione e fare qualcosa, va bene, ma se è ancora un errore, è necessario lanciarlo o un'eccezione diversa, forse con quella appena rilevata come InnerException.

3

mi piacerebbe pensare è ancora possibile impostare il messaggio, per poi tornare nullo o qualunque sia il C# equivalente è

public DataTable ReturnSomething(){ 
    try { 
     //logic here 
     return ds.Tables[0]; 
    } catch (Exception e) { 
     ErrorString=e.Message; 
     return null; 
    } 
} 
2

ne dite di questo:

public DataTable ReturnSomething(out string errorString) 
{ 
    errorString = string.Empty; 
    DataTable dt = new DataTable(); 
    try 
    { 
     //logic here 
    dt = ds.Tables[0]; 
    } 
    catch (Exception e) 
    { 
     errorString = e.Message; 
    } 
    return dt; 
} 
+0

Non si tratta di un errore del compilatore, poiché errorString è un out e non è garantito che sia impostato? –

+0

yeap, hai ragione, lo scrivo in SO editor :) editing! – Canavar

+0

@ScarletGarden: faccio la stessa cosa;] –

3

Se state andando a capo della " non lanciare un percorso di eccezione "(che non sono necessariamente consigliato), potresti seguire l'approccio TryParse utilizzato da MS.

Qualcosa di simile:

private string FillDataTable(out DataTable results) 
{ 

    try 
{ 
    results = new DataTable(); //something like this; 
    return String.Empty; 
} 
catch (Exception ex) 
{ 
    results = null; 
return ex.Message; 

} 

}

6

La variabile ErrorString guarda con sospetto, come una variabile di codice di errore. Si consiglia di utilizzare le eccezioni per trasferire direttamente le informazioni sugli errori, laddove necessario, anziché archiviare gli elementi nei codici di errore.

Si sta effettivamente facendo la stessa cosa con ErrorString di come si farebbe se si lasciasse catturare l'eccezione dal chiamante: rimuovere la responsabilità di rispondere a un errore dal metodo stesso. Questo è un buon obiettivo. Ma l'uso di una stringa di errore non ti porta nulla sull'uso di un'eccezione. In realtà, perdi informazioni in questo modo. Esistono numerosi tipi di errori che potrebbero verificarsi e molti di essi hanno eccezioni speciali associate, con le loro proprietà speciali per contenere informazioni contestuali sull'errore. Archiviando semplicemente il messaggio in una stringa, stai perdendo questa informazione.

Quindi, a meno che l'obiettivo non sia specificamente quello di nascondere il tipo di errore che si sta verificando dal chiamante, è possibile ottenere solo facendo passare l'eccezione.

Un'altra cosa da considerare è se questo è veramente uno scenario di errore. Se lo è, è molto improbabile che il metodo di chiamata si preoccupi del valore restituito. In tal caso, non devi preoccuparti di lasciare andare l'eccezione e non restituire nulla. Se NON è davvero uno scenario di errore, e il chiamante sta per continuare e fare qualcos'altro, beh, è ​​compito del chiamante decidere, giusto? Non c'è ancora molto vantaggio da ottenere restituendo una stringa di errore e un DataTable fittizio o un valore null, oltre a generare l'eccezione con tutte le informazioni di errore contestuali.

0

Puoi farlo come il seguente codice di esempio.

public DataTable ReturnSomething(out string OutputDesc) 
{ 
    try 
     { 
     //logic here 
     OutputDesc = string.Format("Your Successful Message Here..."); 
     return ds.Tables[0]; 
     } 
     catch (Exception e) 
     { 
     OutputDesc =e.Message; 
     return null; 
     } 

} 
Problemi correlati