8 Stimmen

C# IDisposable Frage

Ich habe das folgende Codebeispiel:

public interface IRepository {
   // Whatever
}

public class SampleRepository : IRepository {
   // Implements 'Whatever'
}

public class NHibernateRepository : IRepository, IDisposable {

   // ...

   public void Dispose() { ... }
}

Jetzt - ist das wirklich schlimm? Ich bin mir nicht sicher, aber das scheint ziemlich dasselbe zu sein wie den Destruktor der Basisklasse nicht als virtuell in C++ .

Ich möchte nicht, dass die IRepository Schnittstelle implementieren IDisposable zu implementieren, denn das würde unerwünschte Komplexität und eine Reihe von Klassen mit sich bringen, die ebenfalls IDisposable .


Wie sollte dieser Fall behandelt werden?

Ich bin sicher, dass dies auch bei beliebige Typenhierarchie - wenn einer der abgeleiteten Typen muss verfügbare Ressourcen zu verwalten.

Was soll ich also tun - den Stecker ziehen? IDisposable bis zur allerersten Schnittstelle oder belassen wir es dabei und hoffen, dass die Nutzer zwischen Einweg- und Nicht-Einweg-Repositories unterscheiden?

Ich danke Ihnen.

2voto

Matt Brunell Punkte 9892

Erstens, um Ihre Frage zu beantworten. Das Dispose-Muster unterscheidet sich von einem C++-Destruktor. A Dispose Methode ist dazu bestimmt, Ressourcen zu entsorgen enthalten in der Klasse statt der Beseitigung der Klasse selbst .

Der Grund für die Kennzeichnung von C++-Destruktoren als virtual gibt es in .NET nicht, da jede Instanz eines Referenztyps einen Sync-Block hat, der Laufzeittypinformationen enthält. Auf diese Weise kann der Garbage Collector die richtige Menge an Speicher zurückfordern.

Was die Verlängerung der IRepository con IDisposable Das wäre eine schnelle Lösung, die in den allermeisten Fällen akzeptabel wäre. Der einzige Einwand, den ich sehen kann, ist, dass die Erweiterung der Schnittstelle erfordert, dass alle abgeleiteten Klassen die Schnittstelle implementieren. Auf den ersten Blick mag es einfach erscheinen, eine Schnittstelle mit NOPs zu implementieren (vielleicht sogar mehrfach), aber das sollte man nicht tun müssen. Aber ich kann eine Alternative anbieten.

Stattdessen sollten Sie eine abstrakte Basisklasse verwenden, die das Dispose-Muster implementiert. Diese würde der Struktur der "Standard"-Implementierung des Dispose-Musters folgen.

public abstract class Repository : IDisposable  
{ 
    public void Dispose() { Dispose(true); }
    protected virtual Dispose(bool disposing) {  } 
}

public class NHibernateRepository : Repository { /* Impl here, add disposal. */ }

public class TestRepository : Repository { /* Impl with no resources */ }

Werfen Sie einen Blick auf die Richtlinien für die Entsorgung von Mustern von Microsoft, um ein ausführlicheres Beispiel zu sehen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X