Wie man das Dispose-Muster implementiert, wenn meine Klasse einen Socket & amp; Ereignis?
Sollte es so sein?
%Vor%Ich bin verwirrt ... ist Socket-Klasse "verwalteter Code c # Version von WinSock"? also sollte es freigegeben werden, wenn der Benutzer dispose ("isDisposing IS true") anruft Was ist mit Eventhandlern?
also bei finalisierten Kommentar Abschnitt sollte nur Inptr Objekte frei? Danke.
Ich denke, es gibt viele Möglichkeiten, mit wegwerfbaren Objekten umzugehen, egal ob sie Ereignisse haben oder nicht.
Ist nur eine wilde Vermutung, aber wenn Sie eine Klasse aus dem .net-Framework genommen haben und diese Klasse eine Dispose () -Methode hat, können Sie ziemlich sicher sagen, dass es sich um verwalteten Code handelt, so dass Sie nur das Dispose aufrufen können Methode, anstatt den Destruktor selbst zu erstellen. Dies ist ziemlich veraltet, da Sie, wie Sie in meinem Beispiel sehen, die IDisposable-Schnittstelle auch in Ihren eigenen Klassen implementieren und dann Ihre internen Objekte ordnungsgemäß entsorgen können.
Könnte das für Sie hilfreich sein?
%Vor% Da Socket eine verwaltete Klasse ist, die Richtlinien für die Implementierung von IDisposable
gibt an, dass kein Finalizer benötigt wird. Ein Finalizer führt tatsächlich dazu, dass die Garbage Collection des Objekts verzögert wird, da er den Finalizer während der ersten Garbage Collection aufruft und das Garbage Collection Objekt bei der zweiten Garbage Collection erneut aufruft.
In Bezug auf das Ereignis möchten Sie sich wahrscheinlich von dem Ereignis in der Methode Dispose
abmelden, da die Ereignissubskription bewirkt, dass innerClass
einen Verweis auf die Instanz von MyClass
enthält, es sei denn, das innerClass-Objekt ist kurzlebig. Weitere Informationen zu Ereignissen und zu Dispose finden Sie diese Frage .
Ich denke, dass die folgende Implementierung für Ihr Szenario ausreichen würde:
%Vor% Der Teil in Ihrem Code, den Sie mit "finalisierten nicht gemanagten Code hier" kommentiert haben, sollte nur nicht verwaltete Ressourcen freigeben, z. B. Handles in Form von IntPtr
usw. Seit der Einführung von SafeHandle
in .NET 2.0 müssen Sie dies selten tun, da Sie Ihre% co_de einpacken können % in IntPtr
und behandle sie dann als verwaltete Ressource.
Nach meiner Erfahrung ist der weit verbreitete "soft error" Dispose(disposing)
Mechanismus schlecht durchdacht. Ich bevorzuge "hard error" .
Wenn ich Objekte schreibe, die Dispose()
implementieren, dehne ich normalerweise eine Klasse MyDisposable
aus, die #if DEBUG
wie folgt ausführt:
bool disposed
-Member, das mit false
initialisiert wurde. Dispose()
bestätigt, dass das Objekt nicht bereits entfernt wurde und markiert das Objekt dann als disposed. Auch Objekte, die von MyDisposable
normalerweise abgeleitet werden, setzen !disposed
als Vorbedingung in jeder einzelnen Methode, sogar in jedem einzelnen Getter, voraus.
Das obige garantiert, dass:
Es versteht sich von selbst, dass, wenn nicht #DEBUG
, dann MyDisposable
zu praktisch nichts kompiliert wird, um die Leistung nicht zu behindern.
Folglich versuche ich (wenn möglich) Klassen zu vermeiden, die den "soft error" Dispose(disposing)
-Mechanismus implementieren, ohne sie zuerst in Klassen zu implementieren, die meinen "harten Fehler" implementieren. em> Dispose()
Mechanismus.
Die vorhandenen Antworten sagen es bereits, aber sie sind ziemlich ausführlich. Lassen Sie mich klarer sagen, dass dies alles ist, was Sie brauchen:
%Vor%Dies ist nicht abgekürzt. Sie können alles andere löschen.
Keine Notwendigkeit für einen Finalizer. Keine Notwendigkeit für Null-Tests. Sie können mehrere Male sicher entsorgen.
Das "displace pattern" existiert für finalisierbare Objekte (extrem selten) und für Vererbung (selten). Fast immer hilft dieses Muster überhaupt nicht, sondern beeinträchtigt die Codequalität.