2011-01-06 18 views
6

Duplicar posible:
What is the C# Using block and why should I use it?¿Está utilizando Better?

Mi pregunta: ¿está utilizando using(a){do something with a} mejor que declarar 'a' y el uso de esa manera. es decir: más seguro, más rápido, ...

vea ejemplos para la aclaración.

Ejemplo 1: (sin usar)

StreamWriter sw; 
string line; 
sw = new StreamWriter("D:\\NewCon.xml"); 
sw.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"); 
sw.WriteLine("<config>"); 
for (int i = 0; i >=36; i++) 
{ 
    line = ""; 
    line = "<" + xmlnodes[i] + ">"; 
    line += vals[i]; 
    line += "</" + xmlnodes[i] + ">"; 
    sw.WriteLine(line); 
} 
sw.WriteLine("</config>"); 
sw.Close(); 
sw.Dispose();  

Ejemplo 2: (con el uso)

string line;  
using (sw = new StreamWriter("D:\\NewCon.xml")) 
{ 
    sw.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"); 
    sw.WriteLine("<config>"); 
    for (int i = 0; i >= 36; i++) 
    { 
     line = ""; 
     line = "<" + xmlnodes[i] + ">"; 
     line += vals[i]; 
     line += "</" + xmlnodes[i] + ">"; 
     sw.WriteLine(line); 
    } 
    sw.WriteLine("</config>"); 
} 

Respuesta

11

usando (a) {hacer algo con un}

Esto significa que cuando el bloque de código se realiza con a, el programa llamará a. Desistir. Usted sabe que incluso en el caso de una excepción, a tendrá Dispose invocado. Está esencialmente haciendo:

var a = IDisposable_Something; 
try{.....}finally{a.Dispose();} 

Es más seguro ... no realmente, pero ese no es el punto. El objetivo es asegurarse de que los recursos que deben limpiarse se realicen tan pronto como el programa haya finalizado.

Por lo tanto, el problema con su primer ejemplo es que si en algún punto de la línea se lanza una excepción, no llegará al método Dispose(). El segundo lo hará. Siempre quiere asegurarse de que se llama a Dispose si está allí, porque existe la posibilidad de que las clases IDisposable no se hayan escrito correctamente, y no tendrá el código para asegurarse de que los recursos no administrados se limpien incluso si Dispose() no se llama (esto generalmente se hace en un finalizador). LInk to Dispose Pattern.

La única vez que he visto que implementar puede ser complicado es con el proxy de servicio WCF (y puede solucionar ese problema). Hay un error en el que si el proxy arroja una excepción a veces, causará otra excepción en el método Dispose().

http://blogs.msdn.com/b/jjameson/archive/2010/03/18/avoiding-problems-with-the-using-statement-and-wcf-service-proxies.aspx

Aparte de eso usted debe generalmente tratar de poner un objeto IDisposable en una instrucción using.

+0

¡Gran respuesta gracias por aclarar eso para mí! –

0

Es más seguro en el sentido de que no se olvida de deshacerse de los recursos, especialmente en el caso de una excepción (su código actualmente no detecta ninguno).

Es más sucinto e idiomático ya que utiliza menos líneas de código y la intención de su código se vuelve mucho más clara.

Así que esto:

StreamWriter sw; 
try 
{ 
sw = new StreamWriter("D:\\epkDATA\\NewCon.xml"); 
... 
} 
finally 
{ 
sw.Dispose(); 
} 

es equivalente a:

using(StreamWriter sw = new StreamWriter("D:\\epkDATA\\NewCon.xml")) 
{ 
... 
} 
6

Si se produce una excepción en su primer ejemplo a continuación, el recurso no será desechado.

El uso de using asegura que el recurso se elimine incluso cuando se produce una excepción.

+0

Casi exactamente lo que tenía en mi casilla de Respuesta antes de presionar cargar nuevas respuestas. – Rangoric

1

En primer lugar, el código en el ejemplo 1 debe ser envuelto en un try/finally con el fin de ser funcionalmente equivalente con el código en el ejemplo 2.

Dicho esto, siempre me ha gustado 'usando' bloques para código como este. Creo que generalmente conduce a un código más legible. En cuanto a seguridad o rendimiento, no verá mucha diferencia entre el ejemplo 1 y el ejemplo 2, siempre que use un bloque try/finally en el primer ejemplo.

0

El uso de using es más seguro porque ha garantizado la liberación de recursos declarados al utilizar llaves (...) incluso cuando se produce un error o una salida inesperada.

0

Agregado a las respuestas anteriores, y la parte más importante, si se produce una excepción, se garantiza la llamada al dispose().

2

El ejemplo 1 nunca se debe hacer. Si se lanza una excepción, su llamada Dispose() nunca ocurrirá, lo que podría ser malo. using garantiza la ejecución de Dispose(). La única buena alternativa a la del Ejemplo 1 (además using) sería:

var iDisposableObject = new YourDisposableConstructor(); 
try 
{ 
    // some code 
} 
finally 
{ 
    iDisposableObject.Dispose(); 
} 
0

si claseA hereda de IDisposing.A "utilizando" patrón es igual al siguiente:

IDisposable iDisposableObject = new YourDisposableConstructor(); 
try 
{ 
    // some code 
} 
finally 
{ 
    iDisposableObject.Dispose(); 
} 

así que mejor uso el patrón que usa

Cuestiones relacionadas