2009-05-26 6 views

Respuesta

30

Existen diferencias, pero se reduce al hecho de que un bloque que usa crea sus propios bloques de prueba y alcance.

try 
{ 
    using(IDisposable A = GetDisposable()) 
    { 
     //Do stuff 
    } 
} 
catch 
{ 
    //Handle exception 
    // You do NOT have access to A 
} 


using(IDisposable A = GetDisposable()) //exception here is uncaught 
{ 
    try 
    { 
     //Do stuff 
    } 
    catch 
    { 
     //Handle exception 
     // You DO have access to A 
    } 
} 
+0

A veces puede obtener acceso a 'A' como lo llama, según el tipo de 'Excepción'. Por ejemplo, una 'WebException' tiene una propiedad llamada' Response' que devuelve la instancia 'WebResponse' (o' WebResponse'-derived class) que se usó en el bloque 'using' que puede utilizar como desee. – Sheridan

8

Hay una diferencia entre estos bloques. En el segundo caso, la excepción no se detectará si se lanza en la línea using() (por ejemplo, instanciando un objeto IDisposable y el constructor arroja una excepción). Cuál es mejor dependerá de sus necesidades específicas.

+0

Por el contrario, el uso está fuera del alcance de la captura del primer ejemplo. – Mark

5

Sí. En el primero, el recurso que está "usando" se eliminará antes de que se ejecute el bloque catch. En el último, será eliminado después. Además, la declaración "foo" no está dentro del alcance de la cláusula catch. A "con" bloque es casi azúcar sintáctico tal que

using (foo) 
{ 
} 

es

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

¿Qué comportamiento es "mejor" no es obvia y sin contexto.

2

que presumen decir:

using (var x = new Y(params)) 
{ 
} 

En ambos casos? Entonces la diferencia obvia es el alcance de x. En el segundo caso, puede acceder a x en la cláusula catch. En el primer caso, no pudiste.

También aprovecharé la oportunidad para recordarle que no debe "manejar" una excepción a menos que realmente pueda hacer algo al respecto. Eso incluye el registro de la excepción, que estaría bien, a menos que el entorno en el que estás operando haga el registro por ti (como lo hace ASP.NET 2.0 por defecto).

3

En última instancia, puede combinar ambos métodos para superar tanto inconvenientes:

IFoo f; 
try{ 
    f = new Foo(); 
    f.Bar(); 
catch{ 
    // Do something exceptional with f 
} finally{ 
    if(f != null) f.Dispose(); 
} 
1

La instrucción using asegura que Desechar se llama incluso si se produce una excepción, mientras que la que 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 finally; de hecho, así es como el compilador traduce la sentencia using.

using (Font font1 = new Font("Arial", 10.0f)) 
{ 
    byte charset = font1.GdiCharSet; 
} 

mismo que

{ 
    Font font1 = new Font("Arial", 10.0f); 
    try 
    { 
    byte charset = font1.GdiCharSet; 
    } 
    finally 
    { 
    if (font1 != null) 
     ((IDisposable)font1).Dispose(); 
    } 
} 
2

Como se mencionó anteriormente, sólo el primer método se captura excepciones en la inicialización del objeto IDisposable, y tendrá el objeto en-alcance para el bloque de captura.

Además, el orden de las operaciones para los bloques catch y finally se invertirá dependiendo de su anidación.Tomemos el siguiente ejemplo:

public class MyDisposable : IDisposable 
{ 
    public void Dispose() 
    { 
     Console.WriteLine("In Dispose"); 
    } 

    public static void MethodOne() 
    { 
     Console.WriteLine("Method One"); 
     using (MyDisposable disposable = new MyDisposable()) 
     { 
      try 
      { 
       throw new Exception(); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("In catch"); 
      } 
     } 
    } 

    public static void MethodTwo() 
    { 
     Console.WriteLine("Method Two"); 
     try 
     { 
      using (MyDisposable disposable = new MyDisposable()) 
      { 
       throw new Exception(); 
      } 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine("In catch"); 
     } 
    } 

    public static void Main() 
    { 
     MethodOne(); 
     MethodTwo(); 
    } 
} 

Esto imprimirá:

Method One 
In catch 
In Dispose 
Method Two 
In Dispose 
In catch 
Cuestiones relacionadas