Frage

Ich glaube nicht, diese Frage vor gefragt wurde. Ich bin ein wenig verwirrt über die beste Art und Weise IDisposable auf einer versiegelte Klasse spezifisch, eine versiegelte Klasse zu implementieren, die nicht von einer Basisklasse erbt. (Das heißt, eine „reine versiegelte Klasse“, die mein gemacht ist bis term.)

Vielleicht mit mir in einige von Ihnen zustimmen, dass die Richtlinien für IDisposable Umsetzung sehr verwirrend sind. Das heißt, ich will wissen, dass die Art, wie ich die Absicht IDisposable zu implementieren, ist ausreichend und sicher.

Ich bin etwas P tun / Invoke Code, der eine IntPtr durch Marshal.AllocHGlobal zuordnet und natürlich möchte ich von dem nicht verwalteten Speicher sauber entsorgen die ich angelegt habe. Also ich denke an so etwas wie diese

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public sealed class MemBlock : IDisposable
{
     IntPtr ptr;
     int length;

     MemBlock(int size)
     {
           ptr = Marshal.AllocHGlobal(size);
           length = size;
     }

     public void Dispose()
     {
          if (ptr != IntPtr.Zero)
          {
               Marshal.FreeHGlobal(ptr);
               ptr = IntPtr.Zero;
               GC.SuppressFinalize(this);
          }
     }

     ~MemBlock()
     {
           Dispose();
     }    
}

Ich gehe davon aus, dass, weil MemBlock vollständig abgedichtet ist und nie von einer anderen Klasse abgeleitet wird, dass ein virtual protected Dispose(bool disposing) Umsetzung nicht notwendig ist.

Auch die Finalizerthread unbedingt notwendig? Alle Gedanken begrüßen zu können.

War es hilfreich?

Lösung

Die Finalizerthread ist als Ausweichmechanismus notwendig, um schließlich frei von nicht verwalteten Ressourcen, wenn Sie vergessen haben, Dispose zu nennen.

Nein, Sie sollten keine virtual Methode in einer sealed Klasse deklarieren. Es wäre überhaupt nicht kompilieren. Auch ist es nicht zu empfehlen, um neue protected Mitglieder in sealed Klassen zu deklarieren.

Andere Tipps

Ein kleiner Zusatz; in der Allgemein Fall ist ein gemeinsames Muster eine Dispose(bool disposing) Methode zu haben, so dass Sie wissen, ob Sie in Dispose sind (wo mehr Dinge vorhanden sind) gegen den Rest der Finalizerthread (wo man nicht wirklich berühren sollte andere verbunden verwaltete Objekte).

Zum Beispiel:

 public void Dispose() { Dispose(true); }
 ~MemBlock() { Dispose(false); }
 void Dispose(bool disposing) { // would be protected virtual if not sealed 
     if(disposing) { // only run this logic when Dispose is called
         GC.SuppressFinalize(this);
         // and anything else that touches managed objects
     }
     if (ptr != IntPtr.Zero) {
          Marshal.FreeHGlobal(ptr);
          ptr = IntPtr.Zero;
     }
 }

Joe Duffy Weblog :

  

Für versiegelte Klassen, dieses Muster braucht   nicht gefolgt werden, dh Sie sollten   einfach implementieren Ihre Finalizer und   Entsorgen mit den einfachen Methoden (d.h.   ~ T () (Finalisieren) und Dispose () in C #).   Bei dem letzteren Weg wählen, Ihre   Code sollte noch an die haften   Richtlinien unten in Bezug auf   Umsetzung der Fertigstellung und   entsorgen Logik.

Also ja, sollten Sie gut sein.

Sie tun müssen, die Finalizerthread als Mehrdad erwähnt. Wenn Sie es vermeiden wollen, könnte nehmen Sie einen Blick auf Safehandle . Ich habe nicht genug Erfahrung mit P / Invoke die korrekten Verwendung vorzuschlagen.

Sie können keine virtuellen Methoden in einer versiegelten Klasse deklarieren. Auch geschützte Mitglieder in einer versiegelten Klasse deklarieren gibt Ihnen eine Compiler-Warnung. So haben Sie es richtig umgesetzt. Der Aufruf GC.SuppressFinalize (this) aus dem Finalizerthread ist aus offensichtlichen Gründen nicht notwendig, aber es kann nicht schaden.

Mit einem Finalizerthread wesentlich ist, wenn sie mit nicht verwalteten Ressourcen zu tun, weil sie nicht automatisch befreit sind, haben Sie es in der Finalizerthread zu tun mit automatisch aufgerufen wird, nachdem das Objekt Müll gesammelt wurde.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top