Unterschied zwischen Destruktor-, Entsorgungs- und Finalisierungsmethode

73

Ich studiere, wie Garbage Collector in c # funktioniert. Ich bin über die Verwendung von verwirrt Destructor, Disposeund FinalizeMethoden.

Nach meinen Recherchen und Erkenntnissen weist eine Destructor-Methode in meiner Klasse den Garbage Collector an, die Garbage Collection auf die in der Destructor-Methode angegebene Weise durchzuführen, die für die Instanzen der Klasse nicht explizit aufgerufen werden kann.

Die DisposeMethode soll dem Benutzer die Möglichkeit geben, die Speicherbereinigung zu steuern. Die FinalizeMethode gibt die von der Klasse verwendeten Ressourcen frei, nicht jedoch das Objekt selbst.

Ich bin mir nicht sicher, ob ich es richtig verstehe. Bitte klären Sie die Zweifel. Weitere Links oder Anleitungen sind willkommen.

Victor Mukherjee
quelle

Antworten:

65

Destructor ruft implizit die Finalize-Methode auf, sie sind technisch identisch. Dispose ist für Objekte verfügbar, die die IDisposable-Schnittstelle implementieren.

Möglicherweise sehen Sie: Destruktoren C # - MSDN

Der Destruktor ruft implizit Finalize für die Basisklasse des Objekts auf.

Beispiel aus demselben Link:

class Car
{
    ~Car()  // destructor
    {
        // cleanup statements...
    }
}

Der Code des Destruktors wird implizit in den folgenden Code übersetzt:

protected override void Finalize()
{
    try
    {
        // Cleanup statements...
    }
    finally
    {
        base.Finalize();
    }
}

Ihr Verständnis für den Zerstörer ist richtig:

Von MSDN

Der Programmierer hat keine Kontrolle darüber, wann der Destruktor aufgerufen wird, da dies vom Garbage Collector bestimmt wird . Der Garbage Collector sucht nach Objekten, die von der Anwendung nicht mehr verwendet werden. Wenn ein Objekt als zerstörungsfähig eingestuft wird, ruft es den Destruktor (falls vorhanden) auf und fordert den zum Speichern des Objekts verwendeten Speicher zurück. Destruktoren werden auch aufgerufen, wenn das Programm beendet wird. Es ist möglich, die Speicherbereinigung durch Aufrufen von Collect zu erzwingen. In den meisten Fällen sollte dies jedoch vermieden werden, da dies zu Leistungsproblemen führen kann.

Habib
quelle
Wie kann das Erzwingen der Speicherbereinigung durch Aufrufen zu Collect()Leistungsproblemen führen?
Zerstörer
50

In C # -Begriffen sind ein Destruktor und ein Finalizer grundsätzlich austauschbare Konzepte und sollten verwendet werden, um nicht verwaltete Ressourcen freizugeben , wenn ein Typ erfasst wird, z. B. externe Handles. Es ist sehr selten, dass Sie einen Finalizer schreiben müssen.

Das Problem dabei ist, dass GC nicht deterministisch ist, so dass die Dispose()Methode (via IDisposable) es ermöglicht, die deterministische Bereinigung zu unterstützen . Dies hat nichts mit der Speicherbereinigung zu tun und ermöglicht es dem Aufrufer, Ressourcen früher freizugeben . Es eignet sich auch für die Verwendung mit verwalteten Ressourcen (zusätzlich zu nicht verwalteten). Wenn Sie beispielsweise einen Typ haben, der eine Datenbankverbindung kapselt (z. B.), möchten Sie möglicherweise den Typ entsorgen, um die Verbindung ebenfalls freizugeben.

Marc Gravell
quelle
Ich bin der Meinung, dass die Destructor-Methode nur den Code enthalten sollte, der vor ihrer Zerstörung ausgeführt werden muss. Die Finalize-Methode wird danach meistens von der Superklasse geerbt.
Victor Mukherjee
3
@ VictorMukherjee wieder, sie (Destruktor und Finalizer) sind austauschbar. Es ist das Dispose(), was vor der Zerstörung aufgerufen werden würde , aber das wird weder als Destruktor noch als
Finalisierer bezeichnet
Hallo Marc, ist es richtig zu denken, dass GC meistens deterministisch ist, nur dass die Regeln nicht allgemein bekannt sind? Ich bin kein Experte, lerne immer, ich habe mich gefragt, ob Ihr Kommentar nur allgemein im Zusammenhang mit Finalisierern oder Entsorgen steht. Oder ist es sehr nicht deterministisch (obwohl das vielleicht eine andere Frage für einen anderen Tag ist)?
Alex KeySmith
1
@AlexKeySmith Letzteres muss ich sagen, da es vom Timing, der CPU-Aktivität und externen Faktoren wie dem externen Speicher
abhängt
Danke Marc, das ist sehr nützlich. Selbst wenn die zugrunde liegenden Regeln deterministisch sind, wird sie von weit außerhalb der Kontrolle der App gesteuert und ist praktisch nicht deterministisch. Danke für den Einblick!
Alex KeySmith