2010-07-06 13 views
7

Realmente quiero sacar esto de mi cabeza. Vea el código siguiente:C# usando la declaración

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; 
} 

¿Está dispuesta la tabla de datos? ¿Alguien puede explicar cómo se traduce esto en un bloque try/catch/finally? MSDN afirma que, si se produce una excepción, se llamará al método Dispose, pero ¿qué pasa con la declaración de devolución?

O debo utilizar a continuación código:

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; 

Probablemente, el segundo se debe utilizar, pero sólo necesito iluminación :). Por favor explique. Gracias.

+1

Ponga su declaración donde tú quieras y el Desechar se llamará independientemente. 'Usar' es tu amigo! – Chris

Respuesta

5

using declaración es el azúcar solo sintáctica y que se traduce en try/bloque finally. Comenzando con su código, así es como el compilador de C# traducirá el bloque using en el bloque try/finally.

 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(); 
     } 

Como puede ver en el código, la tabla de resultados se elimina con seguridad independientemente de la declaración de devolución. El bloque de uso solo se asegura de que el objeto se elimine después del alcance.

Su primer código se ve bien para mí y no necesita ser cambiado.

1

El DataTable está descartado (se llama .Dispose) en ambos casos.

Se traduce en try/finally, con Dispose llamando al finally. Finalmente, como su nombre lo indica, se llama incluso cuando llamas al return.

4

Usingno detecta excepciones, solo garantiza la llamada .Dispose().

Esto es así porque,

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

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

La llamada se .Dispose()siempre ser evaluados. La llamada Dispose incluso se evalúa si regresa dentro de su bloque using (antes de que "realmente" regrese). La llamada Dispose incluso se evalúa si se lanza una excepción.

Sin embargo, si se produce una excepción, que excepción será aún prevenir las líneas posteriores de código de ser evaluado (con la excepción de la .Dispose() que es siempre evaluados).

Como tal, si ocurre una excepción, su return no regresará en ninguna de sus declaraciones, pero su DataTable seguirá siendo eliminado.

Si usted quiere garantizar un retorno se produce, incluso cuando se produce un error, que quiere hacer algo como esto:

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

En ambos ejemplos, se llamará a Dispose. Esto se debe a que la instrucción using se expande a un bloque try/finally.

Lea el C# Language Specification (8.13 La declaración using) para conocer los diversos escenarios (para tipos de referencia, tipos de valores no admitibles y tipos dinámicos).

Desde DataTable es un tipo de referencia, su primera muestra se expandirá a lo siguiente:

{ 
    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(); 
    } 
}