Respuestas:
Como varios otros han señalado en general, esto no es un problema.
El único caso que le causará problemas es si regresa en medio de una declaración de uso y, adicionalmente, devuelve la variable de uso de. Pero, de nuevo, esto también le causaría problemas, incluso si no regresó y simplemente mantuvo una referencia a una variable.
using ( var x = new Something() ) {
// not a good idea
return x;
}
Igual de malo
Something y;
using ( var x = new Something() ) {
y = x;
}
return
declaración hace que el final del using
bloque sea inaccesible para cualquier ruta de código. El final del using
bloque debe ejecutarse para que el objeto pueda eliminarse si es necesario.
Está perfectamente bien
Aparentemente estás pensando que
using (IDisposable disposable = GetSomeDisposable())
{
//.....
//......
return Stg();
}
se traduce ciegamente a:
IDisposable disposable = GetSomeDisposable()
//.....
//......
return Stg();
disposable.Dispose();
Lo cual, sin duda, sería un problema y haría que la using
afirmación sea bastante inútil, razón por la cual eso no es lo que hace.
El compilador se asegura de que el objeto esté dispuesto antes de que el control abandone el bloque, independientemente de cómo lo abandone.
Está absolutamente bien, no hay problema en absoluto. ¿Por qué crees que está mal?
Una declaración de uso es solo azúcar sintáctico para un bloque try / finalmente, y como Grzenio dice que está bien regresar también de un bloque try.
Se evaluará la expresión de retorno, luego se ejecutará el bloque finalmente y luego se devolverá el método.
Eso es totalmente aceptable. Una instrucción de uso garantiza que el objeto IDisposable se eliminará sin importar qué.
De MSDN :
La instrucción de uso garantiza que se invoque Dispose incluso si se produce una excepción mientras está llamando a métodos en el objeto. Puede lograr el mismo resultado colocando el objeto dentro de un bloque try y luego llamando a Dispose en un bloque finalmente; de hecho, así es como el compilador traduce la declaración de uso.
El siguiente código muestra cómo using
funciona:
private class TestClass : IDisposable
{
private readonly string id;
public TestClass(string id)
{
Console.WriteLine("'{0}' is created.", id);
this.id = id;
}
public void Dispose()
{
Console.WriteLine("'{0}' is disposed.", id);
}
public override string ToString()
{
return id;
}
}
private static TestClass TestUsingClose()
{
using (var t1 = new TestClass("t1"))
{
using (var t2 = new TestClass("t2"))
{
using (var t3 = new TestClass("t3"))
{
return new TestClass(String.Format("Created from {0}, {1}, {2}", t1, t2, t3));
}
}
}
}
[TestMethod]
public void Test()
{
Assert.AreEqual("Created from t1, t2, t3", TestUsingClose().ToString());
}
Salida:
Se crea 't1'.
Se crea 't2'.
Se crea 't3'.
Se crea 'Creado a partir de t1, t2, t3'.
't3' está dispuesto.
't2' está dispuesto.
't1' está dispuesto.
Los eliminados se invocan después de la declaración de devolución pero antes de la salida de la función.
Quizás no sea 100% cierto que esto sea aceptable ...
Si sucede que está anidando usos y regresando de uno anidado, puede que no sea seguro.
Toma esto como un ejemplo:
using (var memoryStream = new MemoryStream())
{
using (var textwriter = new StreamWriter(memoryStream))
{
using (var csv = new CsvWriter(textwriter))
{
//..write some stuff to the stream using the CsvWriter
return memoryStream.ToArray();
}
}
}
Estaba pasando una DataTable para que se muestre como csv. Con el retorno en el medio, estaba escribiendo todas las filas en la secuencia, pero al csv de salida siempre le faltaba una fila (o varias, dependiendo del tamaño del búfer). Esto me dijo que algo no se estaba cerrando correctamente.
La forma correcta es asegurarse de que todos los usos anteriores se eliminen correctamente:
using (var memoryStream = new MemoryStream())
{
using (var textwriter = new StreamWriter(memoryStream))
{
using (var csv = new CsvWriter(textwriter))
{
//..write some stuff to the stream using the CsvWriter
}
}
return memoryStream.ToArray();
}