2009-05-26 8 views

Antwort

30

Es gibt Unterschiede, aber es läuft darauf hinaus, dass ein using-Block eigene try- und scope-Blöcke erstellt.

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

Manchmal können Sie auf 'A' zugreifen, wie Sie es nennen, abhängig von der Art von 'Exception'. Zum Beispiel hat eine 'WebException' eine Eigenschaft, die 'Response' genannt wird und die' WebResponse' (oder 'WebResponse' abgeleitete Klasse) Instanz zurückgibt, die im' using' Block verwendet wurde, die Sie dann frei verwenden können. – Sheridan

8

Es gibt einen Unterschied zwischen diesen Blöcken. Im zweiten Fall wird die Ausnahme nicht abgefangen, wenn sie in der using() -Zeile ausgelöst wird (z. B. wenn ein IDisposable-Objekt instanziiert wird und der Konstruktor eine Ausnahme auslöst). Welche davon besser ist, hängt von Ihren spezifischen Bedürfnissen ab.

+0

umgekehrt die Verwendung außerhalb des Gültigkeitsbereichs in Fang des ersten Beispiels ist. – Mark

5

Ja. In der ersten wird die Ressource, die Sie verwenden, vor der Ausführung des catch-Blocks entsorgt. In der späteren wird es nachher entsorgt werden. Darüber hinaus fällt die "foo" -Anweisung nicht unter die Fangklausel. A "mit" Block fast syntaktischer Zucker ist so, dass

using (foo) 
{ 
} 

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

ist, das Verhalten ist "besser" ist, ohne Kontext nicht offensichtlich.

2

Ich nehme an, Sie bedeuten:

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

In beiden Fällen? Dann ist der offensichtliche Unterschied der Bereich von x. Im zweiten Fall können Sie in der catch-Klausel auf x zugreifen. Im ersten Fall konnten Sie nicht.

Ich werde auch die Gelegenheit nutzen, Sie daran zu erinnern, eine Ausnahme nicht zu "handhaben", es sei denn, Sie können wirklich etwas dagegen tun. Dazu gehört auch das Protokollieren der Ausnahme, was in Ordnung wäre, es sei denn, die Umgebung, in der Sie arbeiten, protokolliert für Sie (wie es ASP.NET 2.0 standardmäßig tut).

3

Letztlich könnte man eine Kombination beider Methoden zu überwinden beide Nachteile:

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

Die using-Anweisung stellt sicher, dass Entsorgen auch genannt wird, wenn eine Ausnahme auftritt, während Sie Methoden für das Objekt aufrufen. Sie können dasselbe Ergebnis erzielen, indem Sie das Objekt in einen try-Block setzen und dann Dispose in einem finally-Block aufrufen. Genau so wird die using-Anweisung vom Compiler übersetzt.

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

gleiche wie

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

Wie oben erwähnt, werden nur die erste Methode wird Ausnahmen in dem IDisposable Objekt Initialisierung fängt, und wird das Objekt im Gültigkeitsbereich für den Sperranschlag hat.

Zusätzlich wird die Reihenfolge der Operationen für die Fang- und Endblöcke abhängig von ihrer Verschachtelung umgedreht.Nehmen Sie das folgende Beispiel:

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

Dieser Druck wird:

Method One 
In catch 
In Dispose 
Method Two 
In Dispose 
In catch 
Verwandte Themen