2011-05-19 9 views
6

Si tengo algún código como este y aparece un error en la segunda declaración de uso, ¿no se invocará el método de disposición en 1er uso?anidado utilizando instrucciones - cuál no se eliminará

using (System.Data.SqlClient.SqlConnection cn = new System.Data.SqlClient.SqlConnection(cnstr)) 
{ 
     cn.Open(); 

     using (SqlTransaction tran = cn.BeginTransaction(IsolationLevel.Serializable)) 
       { 

--EDIT--

También es mejor para escribir try/finally bloquear o mediante declaración. El compilador interno generará Try/Finally para usar la declaración, pero según los estándares de codificación, ¿cuál es mejor?

+0

Los desechará a ambos, en orden inverso (es decir, el interno se llama primero). –

Respuesta

11

No, se llamarán ambos. El hecho de que se llame a una excepción en la declaración interna no significa que la primera se ignore.

una instrucción using es sólo otra sintaxis para:

var iDisposableItem = new Item(); 

try 
{ 
    ...... 
} 
finally 
{ 
    iDisposableItem.Dispose(); 
} 

por lo que en el ejemplo:

var iDisposableItem = new Item(); 

try 
{ 

    var iDisposableItem2 = new Item(); 

    try 
    { 
     throws exception 
    } 
    finally 
    { 
     iDisposableItem2 .Dispose(); 
    }  

} 
finally 
{ 
    iDisposableItem.Dispose(); 
} 

Ahora lo que debe tenerse en cuenta y lo que hay que tener cuidado es que todo lo que hizo que el La primera excepción podría causar problemas con la declaración de uso externo cuando llama al Dispose(). La excepción podría arrojar el objeto (realmente cualquiera) a un estado en falla y llamar a Dispose podría resultar en otra excepción diferente que "enmascare" al primero. Esta es una de gotcha en la CWF cuando se utiliza using declaraciones: http://msdn.microsoft.com/en-us/library/aa355056.aspx

+0

la excepción surge y la cadena de publicación va con él. – iwayneo

+0

excelente artículo. gracias un montón. – Asdfg

2

Una declaración using es nada más que un try/finally disfrazado, a menos que el proceso se termina por la fuerza, los objetos serán desechados correctamente.

En otras palabras, esto:

using (Type1 x = new Type1()) 
{ 
    // a 
    using (Type2 y = new Type2()) 
    { 
     // b 
    } 
    // c 
} 

es en realidad similar a este (esto se simplifica):

Type1 x = new Type1(); 
try 
{ 
    // a 
    Type2 y = new Type2(); 
    try 
    { 
     // b 
    } 
    finally 
    { 
     y.Dispose(); 
    } 
    // c 
} 
finally 
{ 
    x.Dispose(); 
} 
0

Se dispondrá tanto, y se puede acortarlo como:

using (SqlConnection cn = new SqlConnection(cnstr), SqlTransaction tran = cn.BeginTransaction(IsolationLevel.Serializable)) 
{ 
    cn.Open(); 

} 
+0

no creo que pueda hacer esto ya que ambos son de tipo diferente. – Asdfg

Cuestiones relacionadas