2010-07-06 9 views
7

Voglio davvero togliermi dalla testa. Vedere sotto il codice:C# using statement

using (DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable")) { 
    List<string> resultsList = new List<string>(); 
    foreach (DataRow dataRow in resultTable.Rows) { 
     resultsList.Add(dataRow[0].ToString()); 
    } 
    return resultsList; 
} 

Il datatable è disposto? Qualcuno può spiegare come questo è tradotto in un blocco try/catch/finally? MSDN afferma che se si è verificata un'eccezione, verrà comunque chiamato il metodo Dispose, ma per quanto riguarda l'istruzione return?

o devo solo utilizzare il codice qui sotto:

List<string> resultsList = new List<string>(); 
using (DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable")) { 
    foreach (DataRow dataRow in resultTable.Rows) { 
     resultsList.Add(dataRow[0].ToString()); 
    } 
} 
return resultsList; 

Probabilmente, il secondo dovrebbe essere usato, ma ho solo bisogno di illuminazione :). Spiega per favore. Grazie.

+1

Metti il ​​tuo ritorno dove vuoi, Dispose sarà chiamato a prescindere. 'Usare' è tuo amico! – Chris

risposta

5

using affermazione è zucchero sintattico e si traduce in try/blocco finally. A partire dal tuo codice, ecco come il compilatore C# tradurrà il blocco using in try/finally block.

 try 
     { 
      DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable"); 
      List<string> resultsList = new List<string>(); 
      foreach (DataRow dataRow in resultTable.Rows) 
      { 
       resultsList.Add(dataRow[0].ToString()); 
      } 
      return resultsList; 
     } 
     finally 
     { 
      resultTable.Dispose(); 
     } 

Come si può vedere dal codice, la tabella dei risultati viene eliminata di sicuro indipendentemente dall'istruzione di reso. Il blocco using si assicura solo che l'oggetto venga eliminato dopo l'ambito.

Il tuo primo codice mi sembra a posto e non è necessario cambiarlo.

1

Il DataTable è disposto (.Dispose viene chiamato) in entrambi i casi.

E 'tradotto in try/finally, conchiamato nello finally. Infine, come suggerisce il nome, viene chiamato anche quando si chiama return.

4

Usingnon fa eccezioni di cattura, garantisce solo la chiamata .Dispose().

Questo perché,

using (ResourceType resource = new ResourceType()) è equivalente a:

ResourceType resource; 
try 
{ 
    resource = new ResourceType(); 
    /* The insides of the using block */ 
} 
finally 
{ 
    resource.Dispose(); 
} 

Il .Dispose() chiamata sarà sempre essere valutati. La chiamata Dispose viene valutata anche se si ritorna all'interno del blocco using (prima che "realmente" restituisca). La chiamata Dispose viene persino valutata se viene generata un'eccezione.

Tuttavia, se viene generata un'eccezione, tale eccezione sarà ancora evitare successive linee di codice venga valutata (con l'eccezione del .Dispose() quali è sempre valutate).

In questo modo, se si verifica un'eccezione, il tuo return non verrà restituito in nessuna delle tue dichiarazioni, ma il tuo DataTable sarà comunque eliminato.

Se si vuole garantire un ritorno si verifica anche quando si verifica un errore, si vuole fare qualcosa di simile:

List resultsList = new List(); 
try 
{ 
    using (DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable")) 
    { 
     foreach (DataRow dataRow in resultTable.Rows) 
     { 
      resultsList.Add(dataRow[0].ToString()); 
     } 
    } 
} 
catch 
{ 
} 
return resultsList; 
1

In entrambi i casi, verrà chiamato Dispose. Questo perché l'istruzione using si espande in un blocco try/finally.

Leggi l'articolo C# Language Specification (8.13 L'istruzione using) per scoprire i vari scenari (per tipi di riferimento, tipi di valori non annullabili e tipi dinamici).

Dal DataTable è un tipo di riferimento, il primo campione si espanderà al seguente:

{ 
    DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable"); 
    try { 
     List<string> resultsList = new List<string>(); 
     foreach (DataRow dataRow in resultTable.Rows) { 
      resultsList.Add(dataRow[0].ToString()); 
     } 
     return resultsList; 
    } 
    finally { 
     if (resultTable != null) ((IDisposable)resultTable).Dispose(); 
    } 
}