2010-03-03 14 views
93

Volviendo un valor método de dentro una instrucción using que consigue un DataContext parece funcionar siempre bien, así:¿Hay algún efecto secundario de regresar desde el interior de una instrucción using()?

public static Transaction GetMostRecentTransaction(int singleId) 
{ 
    using (var db = new DataClasses1DataContext()) 
    { 
     var transaction = (from t in db.Transactions 
           orderby t.WhenCreated descending 
           where t.Id == singleId 
           select t).SingleOrDefault(); 
     return transaction; 
    } 
} 

Pero siempre me siento como si debiera ser cerrar algo antes de romper fuera de los soportes de uso, por ejemplo definiendo la transacción antes de la declaración que usa, obtenga su valor dentro de los corchetes, y luego devuelva después de los corchetes.

¿Definir y devolver la variable fuera de los corchetes de uso sería una mejor práctica o conservaría los recursos de alguna manera?

+1

Puede ser interesante mirar la IL general para encontrar variantes de esto. Sospecho que habría poca diferencia en el IL generado. Normalmente ni siquiera me molestaría en declarar la transacción var; solo devuelve el resultado de la expresión. – Jonesie

+3

@Manish, ¿por qué sería? –

Respuesta

120

No, creo que es más claro de esta manera. No se preocupe, Dispose se seguirá llamando "a la salida", y solo después de, el valor de retorno se evaluará por completo. Si se lanza una excepción en cualquier punto (incluida la evaluación del valor de retorno) también se llamará al Dispose.

Aunque es cierto que podría tomar la ruta más larga, se trata de dos líneas adicionales que acaba de agregar costra y el contexto extra para no perder de vista (mental). De hecho, realmente no necesita la variable local adicional, aunque puede ser útil en términos de depuración. Usted podría acaba de tener:

public static Transaction GetMostRecentTransaction(int singleId) 
{ 
    using (var db = new DataClasses1DataContext()) 
    { 
     return (from t in db.Transactions 
       orderby t.WhenCreated descending 
       where t.Id == singleId 
       select t).SingleOrDefault(); 
    } 
} 

De hecho, incluso podría tener la tentación de utilizar la notación de puntos, y poner la enfermedad Where dentro del SingleOrDefault:

public static Transaction GetMostRecentTransaction(int singleId) 
{ 
    using (var db = new DataClasses1DataContext()) 
    { 
     return db.Transactions.OrderByDescending(t => t.WhenCreated) 
           .SingleOrDefault(t => t.Id == singleId); 
    } 
} 
+1

Ya que es usted @jon, ¿sigue siendo seguro si se arroja una excepción dentro del bloque de uso? –

+5

sí.usar es simplemente azúcar sintáctica para una construcción try/finally –

+0

@Mitch, gracias :-) –

23

un vistazo a este

The CLR converts your code into MSIL. And the using statement gets translated into a try and finally block. This is how the using statement is represented in IL. A using statement is translated into three parts: acquisition, usage, and disposal. The resource is first acquired, then the usage is enclosed in a try statement with a finally clause. The object then gets disposed in the finally clause.

+4

Una visión interesante. Gracias. – Kangkan

+1

Eso traduce la pregunta a: ¿Algún efecto secundario de regresar del try-block de un try-finally? –

+2

No, al final siempre se llamará. http://www.techinterviews.com/interview-questions-for-c-developers –

4

Hay no efectos secundarios de regresar de una declaración using().

Si hace que el código más legible sea otra discusión.

0

Creo que es todo lo mismo. No hay nada malo en el código. Al .NET framework no le importaría dónde se crea el objeto. Lo que importa es si se hace referencia o no.

0

Sí, puede haber un efecto secundario. Por ejemplo, si se utiliza la misma técnica en el método ASP.NET MVC Acción, obtendrá el siguiente error: "La instancia de ObjectContext se ha dispuesto y ya no se puede utilizar para las operaciones que requieren una conexión"

public ActionResult GetMostRecentTransaction(int singleId) 
{ 
    using (var db = new DataClasses1DataContext()) 
    { 
     var transaction = (from t in db.Transactions 
           orderby t.WhenCreated descending 
           where t.Id == singleId 
           select t).SingleOrDefault(); 
     return PartialView("_transactionPartial", transaction); 
    } 
} 
+2

si define la transacción fuera de la instrucción using, obtendrá el mismo error. el uso de palabra clave no está relacionado en este caso. – Costa

Cuestiones relacionadas