2010-08-23 13 views

Antwort

12

Wenn Sie die using statement die gekapselten verwenden müssen bereits implementieren IDisposable sonst wird der Compiler einen Fehler aus. Betrachten Sie daher die IDisposable-Implementierung als Voraussetzung für die Verwendung. Wenn Sie die using-Anweisung für Ihre benutzerdefinierte Klasse verwenden möchten, müssen Sie IDisposable dafür implementieren. Dies ist jedoch etwas rückständig zu tun, da es keinen Sinn hat, dies zu tun. Nur wenn Sie etwas wie eine nicht verwaltete Ressource zu entsorgen haben, sollten Sie es implementieren.

// To implement it in C#: 
class MyClass : IDisposable { 

    // other members in you class 

    public void Dispose() { 
     // in its simplest form, but see MSDN documentation linked above 
    } 
} 

Dies ermöglicht Ihnen:

using (MyClass mc = new MyClass()) { 

    // do some stuff with the instance... 
    mc.DoThis(); //all fake method calls for example 
    mc.DoThat(); 

} // Here the .Dispose method will be automatically called. 

effektiv das ist das gleiche wie das Schreiben:

MyClass mc = new MyClass(); 
try { 
    // do some stuff with the instance... 
    mc.DoThis(); //all fake method calls for example 
    mc.DoThat(); 
} 
finally { // always runs 
    mc.Dispose(); // Manual call. 
} 
+0

Können Sie ein Codebeispiel anzeigen, plz? – Troy

+1

@Troy: Beispiel hinzugefügt, um die Erklärung hervorzuheben. –

+2

Eigentlich ist es ein ziemlich nützliches Muster, wenn Sie einen "Sandwich" -Code haben, der einiges in einem finally-Abschnitt ausführen muss. Ein häufiges Szenario wäre beispielsweise ein Besetzt-Cursor, die Schritte sind ... 1./Kopieren Sie den vorhandenen Cursor 2./setzen Sie den Cursor auf Ihren Warte-Cursor 3./In einem letzten Abschnitt kopieren Sie das Original zurück. Mit einer Verwendung und IDisposable Sie könnten dann Code so etwas wie mit (Busy.WaitCursor) { // Wo Waitcursor ist eine statische Eigenschaft schreiben, die eine Instanz von Besetzt den Konstruktor Kopien und Sätze und die dispose() wieder- kehrt Sätze. } –

5

Sie sind etwas verwirrend. Sie können das Schlüsselwort using nur für etwas verwenden, das IDisposable implementiert.

Edit: Wenn Sie die Verwendung von Keyword verwenden, müssen Sie Dispose nicht explizit aufrufen, wird automatisch am Ende des using-Blocks aufgerufen werden. Andere haben bereits Beispiele dafür veröffentlicht, wie die using-Anweisung in eine try-finally-Anweisung übersetzt wird, wobei Dispose im finally-Block aufgerufen wird.

+0

Sie können das Schlüsselwort "using" verwenden, wenn Sie Daten aus einem Recordset lesen, richtig? – Troy

+1

@Troy, ja, weil IDataReader IDisposable implementiert. –

+0

Nur wenn alles, was Ihr Recordset umhüllt, IDisposable implementiert. Wenn es kompiliert wird, implementiert es IDisposable .... –

2

Verwendung wird nur Einweg Objekte entsorgen. Ein Wrapping eines using-Blocks um ein Objekt, das IDisposable nicht implementiert, ist eher nutzlos wird tatsächlich einen Compiler-Fehler verursachen.

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement. The using statement calls the Dispose method on the object in the correct way, and it also causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and cannot be modified or reassigned.

The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler.

+1

In der Tat ist es ein Compilerfehler. – Timwi

12

Sie nicht das eine ohne das andere haben.

Wenn Sie schreiben:

using(MyClass myObj = new MyClass()) 
{ 
    myObj.SomeMthod(...); 
} 

Compiler so etwas wie dies generieren:

MyClass myObj = null; 
try 
{ 
    myObj = new MyClass(); 
    myObj.SomeMthod(...); 
} 
finally 
{ 
    if(myObj != null) 
    { 
     ((IDisposable)myObj).Dispose(); 
    } 
} 

So wie Sie während using Schlüsselwort mit sehen es wird angenommen,/erforderlich, dass IDisposable implementiert ist.

+0

+1, aber nicht vorausgesetzt - erforderlich. Der Compilercode, den Sie hier gezeigt haben, würde mit einer ungültigen Cast-Ausnahme auskommen, wenn der Typ IDisposable nicht implementiert hat. Dies ist der Grund, warum der Compiler dies verhindert, indem er einen Kompilierzeitfehler gibt, wodurch IDisposable benötigt wird, nicht angenommen wird, um in einer Verwendung verwendet zu werden. –

+0

@Jimmy ja du hast Recht, sagend angenommen ich meinte das. Die Antwort wurde aktualisiert. – Incognito

4

Ja, die Verwendung von Keyword ist syntaktischer Zucker für diese Art von Muster ... (von Msdn)

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

Edit: ein nützliches Beispiel.

Wenn Sie finden Sie die Dinge in einem endlich Abschnitt consistantly tun, zum Beispiel eines Cursor zurück auf den Standard Zurücksetzen nachdem es auf einen Wartecursor gesetzt zu haben, das ist ein Kandidat für dieses Muster ...

public class Busy : IDisposable 
    { 

    private Cursor _oldCursor; 

    private Busy() 
    { 
     _oldCursor = Cursor.Current; 
    } 

    public static Busy WaitCursor 
    { 
     get 
     { 
     Cursor.Current = Cursors.WaitCursor; 
     return new Busy(); 
     } 
    } 

    #region IDisposable Members 

    public void Dispose() 
    { 
     Cursor.Current = _oldCursor; 
    } 

    #endregion 
    } 

Genannt wie ...

using(Busy.WaitCursor) 
{ 
    // some operation that needs a wait cursor. 
} 
1

Die Verwendung von Keyword bereits implementiert, so dass, wenn Sie die Verwendung von Keyword verwenden, müssen Sie nicht IDisposable aufrufen

1

Sie müssen IDisposable implementieren mit zu verwenden. Wenn Sie versuchen,() auf eine Art zu verwenden, verwenden, die nicht IDisposable nicht implementiert Sie die folgende Kompilierung Fehler:

error CS1674: 'SomeType': type used in a using statement must be implicitly convertible to 'System.IDisposable'