2013-05-17 12 views
15

In this answer Ich fand,Dispose() zum Bereinigen verwalteter Ressourcen?

Cleanup die nicht verwalteten Ressourcen in der Finalize-Methode und die verwalten diejenigen in der Dispose-Methode, wenn das Entsorgen/finalisieren Muster hat im Code verwendet.

Und später fand ich this nice article über finalisieren und entsorgen und bekam eine klare Vorstellung davon. Der Artikel hat den folgenden Code (Page 3), die Konzepte zu erklären:

class Test : IDisposable 
{ 
    private bool isDisposed = false; 

    ~Test() 
    { 
     Dispose(false); 
    } 

    protected void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      // Code to dispose the managed resources of the class 
     } 
     // Code to dispose the un-managed resources of the class 

     isDisposed = true; 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 
} 

Aber darunter, die gleiche Note (die ich am Anfang dieser Frage enthalten) erscheint.

Das Entsorgen/Finalisierung Muster Microsoft empfiehlt, dass Sie implementieren beide Entsorgen und finalisieren, wenn sie mit nicht verwalteten Ressourcen arbeiten. Die richtige Reihenfolge wäre dann , damit ein Entwickler Dispose aufrufen kann. Die Finalize-Implementierung würde ausführen und die Ressourcen würden immer noch freigegeben, wenn das Objekt Müll gesammelt wird, selbst wenn ein Entwickler die Methode Dispose explizit nicht aufgerufen hat. Francesco Balena schreibt in seinem Blog " Dispose/Finalize Muster sollte nur verwendet werden, wenn Ihr Typ ruft nicht verwalteten Code, der nicht verwalteten Ressourcen (einschließlich nicht verwalteten Speicher) reserviert und gibt ein Handle, das Sie schließlich die Ressource freigeben müssen. Beide entsorgen und finalisieren müssen bis zu ihren Eltern Objekte durch Aufruf der entsprechenden Methoden ihrer Eltern, nachdem sie entsorgt oder ihre eigenen Mitglieder abgeschlossen haben ". Einfach gesagt, bereinigen Sie die nicht verwalteten Ressourcen in der Finalize-Methode und die verwalteten in der Dispose-Methode, wenn das Dispose/Finalize-Muster in Ihrem Code verwendet wurde.

Jetzt bin ich wieder verwirrt. Im gesamten Artikel und im Codebeispiel wird gezeigt, dass nicht verwaltete Ressourcen in Dispose() freigegeben werden sollten. Aber was ist die Relevanz dieses Kommentars?

Edit:

Wie es wird bestätigt, dass diese Zeile:

Einfach gesagt, Bereinigung der nicht verwalteten Ressourcen in der Finalize-Methode und die verwalteten diejenigen in der Dispose-Methode, wenn das Entsorgen/Finalisierung Muster hat sich in Ihrem Code

fehlerhaft ist, ich this answer bearbeitet verwendet.

Antwort

30

Sehen Sie es sehr einfach.

  1. Wenn Sie mit nicht verwalteten Ressourcen handelt - Umsetzung sowohl Entsorgen und Finalisierung.Dispose soll von Entwicklern aufgerufen werden, um die Ressourcen freizugeben, sobald sie sehen, dass sie für sie nicht mehr benötigt werden. Wenn sie vergessen, den Dispose aufzurufen, ruft Framework das finalize in seinem eigenen GC-Zyklus auf (normalerweise wird es seine eigene süße Zeit nehmen).
  2. Wenn Sie sich nicht mit nicht verwalteten Ressourcen beschäftigen - Dann tun Sie nichts. Implementieren Sie weder Finalisieren noch Dispose.
  3. Wenn Ihr Objekt intern Disposable-Objekte verwendet - Sie implementieren Dispose(), wenn Sie einen Verweis auf ein Objekt eines Typs erstellt haben und beibehalten, der Dispose() implementiert und den Sie noch nicht entfernt haben.

Einige klassische Beispiele:

System.IO.FileStream Objekt verwaltet die Sperre/Stream-Dateien verarbeitet. So implementiert es sowohl zu entsorgen als auch zu finalisieren. Wenn der Entwickler es entsorgt, kann das andere Programm sofort darauf zugreifen. Wenn er vergisst, es zu entsorgen, dann schließt es das Framework ab und schließt die Griffe später in seinem GC-Zyklus.

System.Text.StringBuilder Dosis keine nicht verwaltete Ressource. Also nein, nein, fertigstellen.

Was das Muster betrifft, was es bedeutet, zu
// Code to dispose the managed resources of the class
, dass die Entsorgung Methoden der .NET-Objekte aufrufen, die Sie innerhalb dieser Klasse als Komponenten haben

Und

// Code to dispose the un-managed resources of the class Mittel zur Schließen Sie die rohen Handles und Zeiger. Hier ist Ihre aktualisierten Code mit Beispielen

class Test : IDisposable 
    { 
    private bool isDisposed = false; 

    ~Test() 
    { 
     Dispose(false); 
    } 

    protected void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
     // Code to dispose the managed resources of the class 
     internalComponent1.Dispose(); 
     internalComponent2.Dispose(); 
     } 

     // Code to dispose the un-managed resources of the class 
     CloseHandle(handle); 
     handle = IntPtr.Zero; 

     isDisposed = true; 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 
    } 

hier eine alte Frage explaing es http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/186947fd-e6da-41fb-9998-3b1e6223f17c

+0

Tatsächlich gibt es überhaupt keine Bereinigung verwalteter Ressourcen. Ich sehe seinen Standpunkt in keiner Weise relevant. Der maximale Wert, den Sie zum Bereinigen einer verwalteten Ressource verwenden können, besteht darin, sie NULL zuzuweisen. Das ist völlig unnötig mit solch einem guten GC eingebaut. –

+0

Das ist ein Artikel, der 2006 geschrieben wurde, also würde ich mich eigentlich nicht wirklich darum kümmern. –

+2

Es ist nicht ganz so einfach. Sie sollten auch 'Dispose()' implementieren, wenn Sie einen Verweis auf * any * -Objekt eines Typs erstellt und behalten haben, der 'Dispose()' implementiert und den Sie noch nicht entfernt haben. Einige Typen verwenden keine nicht verwalteten Ressourcen, aber sie haben Dinge wie Abonnements für Ereignisse, die sie in ihren 'Dispose()' - Methoden aushängen müssen. Sie müssen solche Objekte entsorgen, selbst wenn sie keine nicht verwalteten Ressourcen verwenden, sonst können Sie eine Art Speicherleck haben. Dies trifft oft besonders auf UI-Klassen zu, die von 'Control' oder' UserControl' abgeleitet sind. –

3

Wenn ein Foo hat Ressourcen, die von deterministischen Bereinigung profitieren, aber keine, die sinnvollerweise gereinigt in einem Finalizer werden kann, ist es sollte IDisposable implementieren, sollte aber nicht Finalize überschreiben oder einen Destruktor haben. Wenn eine Klasse mehrere Ressourcen enthält und mindestens eine davon in einem Finalizer bereinigt werden kann, sollte jede diskrete Ressource, die in einem Finalizer bereinigt werden kann, in ein eigenes Finalizer/Destruktor-ausgestattetes Objekt (das in a definiert werden kann) eingekapselt werden geschützter geschachtelter Klasse), und die Klasse, die diese Ressourcen enthalten würde, sollte Verweise auf die Wrapper-Objekte enthalten. Sobald dies erledigt ist, passt die äußere Klasse das Muster für Klassen mit einer Dispose Methode, aber kein Finalizer/Destruktor.