2009-04-20 7 views
7

Ich habe in .NET seit vier Jahren programmiert (meistens C#) und ich benutze IDiposable ausgiebig, aber ich muss noch einen Bedarf für einen Finalisierer finden. Für was sind die Finisher?Was sind Finisher für?

+5

Btw, ich bin Englisch, und ich habe festgestellt, dass es eine * wirklich * * wirklich * gute Idee ist, sich an die Schreibweise "finalisieren" und "initialisieren" mit einem z, nicht einem s, zu gewöhnen. Ansonsten können Sie die verdammten Dinge nie finden, wenn Sie in der Dokumentation danach suchen! –

+1

@onebyone - dito. Ebenso, Farbe ... es hat mich früher irritiert, aber jetzt betrachte ich sie als den Fachbegriff für die Industrie, und erledige die Arbeit; -p –

+0

Ich habe versucht, mich selbst zu trainieren - ich benutze es in der Dokumentation und in der Öffentlichkeit vor dem Code, aber ich kann mich einfach nicht dazu bringen, es im "richtigen Leben" zu tun. –

Antwort

10

Ein Finalizer ist ein letzter Versuch, um sicherzustellen, dass etwas korrekt bereinigt wird und normalerweise für Objekte reserviert ist, die unmanaged Ressourcen wie nicht verwaltete Handles usw., die nicht Müll sammeln gesammelt werden.

Es ist selten, einen Finalizer zu schreiben. Glücklicherweise (und im Gegensatz zu IDisposable) müssen Finalizer nicht propagiert werden; Wenn Sie also eine ClassA mit einem Finalizerthread haben, und eine ClassB die ClassA Wraps, dann ist ClassB kein Finalizerthread brauchen - aber sehr wahrscheinlich beide ClassA und ClassB würde IDisposable implementieren.

Für verwalteten Code ist normalerweise IDisposable ausreichend. Selbst wenn Sie nicht sauber aufräumen, werden eventuell die verwalteten Objekte gesammelt (vorausgesetzt, sie werden freigegeben).

1

Finalizer dienen zum Säubern von Ressourcen, wenn sie nicht entsorgt wurden.

IE, nichts erzwingt, dass Sie jemals Dispose() aufrufen, aber Finalizer werden automatisch vom Garbage Collector aufgerufen.

Diese Funktionalität sollte nicht verlässlich sein, da es keine Garantie gibt, wann (oder ob) Garbage Collection zu Ihrem Objekt gelangt.

2

Finalizer sind als Mechanismus zum Freigeben von Ressourcen gedacht, die nicht von Garbage Collector gesteuert werden, wie ein nicht verwalteter Handle. Während Dispose könnte es tun, ist es nicht garantiert, dass der Verbraucher es nennen wird.

4

Finalizer sind nur zum Freigeben unmanaged Ressourcen wie GDI Bitmap-Handles zum Beispiel. Wenn Sie keine nicht verwalteten Ressourcen zuweisen, benötigen Sie keine Finalizer. Im Allgemeinen ist es eine schlechte Idee, ein verwaltetes Objekt in einem Finalizer zu berühren, da die Reihenfolge der Finalisierung nicht garantiert ist.

Eine andere nützliche Technik, die einen Finalizer verwendet, besteht darin, zu bestätigen, dass Dispose aufgerufen wurde, wenn die Anwendung dazu aufgefordert wird. Diese fangen helfen können Fehler in einer Debug-Build-Codierung:

void Dispose() 
{ 
    GC.SuppressFinalize(this); 
} 
#if DEBUG 
~MyClass() 
{ 
    Debug.Fail("Dispose was not called."); 
} 
#endif 
1

Wikipedia says:

... ein Finalizerthread ist ein Stück Code, dass sorgt dafür, dass bestimmte notwendige Maßnahmen ergriffen werden, wenn ein erworbenes Ressource ... wird nicht mehr verwendet werden [weil der Besitz Objekt Müll gesammelt wurde]

Und wenn Sie beim Schreiben von IDisposables keinen Finalisierer verwenden, haben Sie möglicherweise Speicherlecks, weil es keine Garantie gibt, dass ein Besitzer tatsächlich Dispose() aufruft.

MS selbst empfehlen Sie etwas Ähnliches wie diese in Ihre Implementierer schreiben:

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

    protected virtual void Dispose(bool disposing) 
    { 
     if (!this.isDisposed) 
     { 
      if (disposing) 
      { 
       GC.SuppressFinalize(this); 
      } 
     } 
     //Dispose of resources here 
     this.isDisposed = true; 
    } 

    ~DisposableSafe() 
    { 
     this.Dispose(false); 
    } 

    private bool isDisposed = false; 

Ich persönlich nicht ausstehen kann die Copy-Paste so neige ich dazu, für die Wiederverwendung, dass in einer abstrakten Klasse zu wickeln.

+0

Wenn Ihre Klasse nicht direkt mit * nicht verwalteten * Ressourcen arbeitet, benötigen Sie wahrscheinlich keinen Finalisierer. Verwaltete Ressourcen sollten schließlich vom GC behandelt werden, unabhängig davon, ob der Benutzer Dispose anruft oder nicht. – LukeH

+0

Das hat mich dazu gebracht, "möglicherweise" anstelle von "wahrscheinlich" zu schreiben und ich machte mir darüber Sorgen. Aber es ist sowieso nicht wahr. Wenn Ihre Klasse ein anderes IDisposable implementiert, dann müssen Sie auch Dispose() aufrufen. Und wie es geht, von MSDN "Die primäre Verwendung dieser Schnittstelle ist die Freigabe nicht verwalteter Ressourcen." – annakata