2009-05-26 15 views

risposta

30

Ci sono delle differenze, ma in sostanza si riduce al fatto che un blocco usando crea i propri blocchi try e scope.

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 volte è possibile accedere a "A" come si chiama, a seconda del tipo di "Eccezione". Ad esempio, una 'WebException' ha una proprietà chiamata' Response' che restituisce l'istanza 'WebResponse' (o' derivata da WebResponse') che è stata usata nel blocco 'using' che sei libero di usare come desideri. – Sheridan

8

C'è una differenza tra questi blocchi. Nel secondo caso l'eccezione non verrà rilevata se viene lanciata nella riga using() (ad esempio creando un'istanza di un oggetto IDisposable e il costruttore genera un'eccezione). Quale è meglio dipenderà dalle tue esigenze specifiche.

+0

Al contrario, l'utilizzo è fuori del campo di applicazione nel pescato del primo esempio. – Mark

5

Sì. Nel primo, la risorsa che si sta "utilizzando" verrà eliminata prima dell'esecuzione del blocco catch. In seguito, sarà smaltito in seguito. Inoltre, la dichiarazione "foo" non rientra nell'ambito di applicazione della clausola di cattura. Un blocco "con" è quasi zucchero sintattico tale che

using (foo) 
{ 
} 

è

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

Quale comportamento è "migliore" non è ovvio senza contesto.

2

Presumo che cercavi:

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

In entrambi i casi? Quindi l'ovvia differenza è lo scopo di x. Nel secondo caso, è possibile accedere a x nella clausola catch. Nel primo caso, non è possibile.

Coglierò inoltre l'occasione per ricordarti di non "gestire" un'eccezione a meno che tu non possa davvero fare qualcosa al riguardo. Ciò include la registrazione dell'eccezione, il che sarebbe ok, a meno che l'ambiente in cui stai operando esegua la registrazione (come per default ASP.NET 2.0).

3

In ultima analisi, è possibile combinare entrambi i metodi per superare sia SVANTAGGI:

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

L'istruzione using assicura che Dispose viene chiamato anche se un'eccezione si verifica mentre si sta chiamando metodi sull'oggetto. È possibile ottenere lo stesso risultato inserendo l'oggetto in un blocco try e quindi chiamando Dispose in un blocco finally; in effetti, questo è il modo in cui l'istruzione using viene tradotta dal compilatore.

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

stessa

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

Come menzionato sopra, solo il primo metodo prenderà eccezioni nella inizializzazione dell'oggetto IDisposable, ed avrà l'oggetto in-scope per il blocco di cattura.

Inoltre, l'ordine delle operazioni per il blocco e infine i blocchi verrà invertito a seconda del loro annidamento.Prendiamo il seguente esempio:

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(); 
    } 
} 

Questo stamperà:

Method One 
In catch 
In Dispose 
Method Two 
In Dispose 
In catch 
Problemi correlati