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.

15voto

Jon Skeet Punkte 1325502

Ja, ich würde sagen, das ist schlecht - weil man nicht alle Repositories auf die gleiche Weise nutzen kann.

Ich persönlich würde die Repository-Schnittstelle erweitern IDisposable - Es ist doch einfach genug, sie mit einem No-op zu implementieren.

Dies ist genau die gleiche Wahl, die auch von Stream , TextReader y TextWriter im Hauptrahmen. StringWriter (zum Beispiel) braucht nichts zu entsorgen... aber TextWriter ist immer noch wegwerfbar.

Dies alles geschieht aus folgenden Gründen IDisposable ist in gewisser Weise eine merkwürdige Schnittstelle: Sie vermittelt nicht etwas, das angeboten Anrufern... es vermittelt etwas, das erforderlich von Anrufern (oder zumindest dringend empfohlen, mit möglichen Problemen, wenn Sie nicht mitmachen).

9voto

poindexter12 Punkte 1755

Das einzige Problem, das Sie haben könnten, ist, wenn Sie eine Art von Fabrik, Inversion of Control oder Dependency Injection Muster / Framework verwenden. Wenn Sie das Objekt jemals als Schnittstelle verwenden möchten, werden Sie nie in der Lage sein, dies zu tun:

IRepository repo = Factory.GetRepository();
repo.Dispose();

Vielleicht möchten Sie ein INHibernateRepository einführen, das IDisposable implementiert. Da IDisposable in der Regel eine Operation auf niedriger Ebene ist, ist es kein großes Problem, wenn Ihre Schnittstellen diese Schnittstelle implementieren.

4voto

Henk Holterman Punkte 249753

Nein, ziehen Sie den IDisposable nicht "hoch". Halten Sie Schnittstellen atomar, einfach und unabhängig.

Solange man nicht argumentieren kann, dass IDisposable eine grundlegende Eigenschaft von IRepository ist (und SampleRepository zeigt, dass dies nicht der Fall ist), sollte es keine Ableitung zwischen den beiden geben.

3voto

Matt Lacey Punkte 64983

Das scheint mir völlig in Ordnung zu sein. Wo liegt das Problem?

3voto

supercat Punkte 72939

Was Sie beschrieben haben, ist in Ordnung, allerdings mit einer wichtigen Einschränkung: Ein Objekt eines Typs, der seiner Basis "IDisposable" hinzugefügt hat, darf niemals an einen Verbraucher weitergegeben werden, der das Objekt für eine unbekannte Dauer halten oder persistieren könnte.

Grundsätzlich muss sich der Eigentümer eines IDisposable-Objekts entweder selbst um die Entsorgung des Objekts kümmern oder das Objekt an einen neuen Eigentümer übergeben, der die Verantwortung übernehmen kann und diese auch wahrnimmt (*). Ursprünglich gehören IDisposable-Objekte in der Regel ihrem Ersteller, aber Übergaben sind üblich. Ein Verweis auf ein IDispoable-Objekt kann an ein anderes Objekt weitergegeben werden, ohne dass das Eigentum übertragen wird; in diesem Szenario ist der Eigentümer immer noch dafür verantwortlich, das Objekt zu entsorgen, wenn es nicht mehr benötigt wird. Dazu muss der Eigentümer wissen, dass das Objekt nicht mehr benötigt wird. Die gängigsten Muster sind:

  1. Das Objekt wird als Parameter an eine Methode übergeben; das Objekt, das die Methode hostet, wird das Objekt nach der Rückkehr der Methode nicht mehr verwenden.
  2. Das Objekt wird als Parameter an eine Methode übergeben, die es in einem Feld eines Objekts speichert, aber dieses Objekt kann später irgendwie aufgefordert werden, die Referenz zu zerstören.
  3. Das Wegwerfobjekt wird als Parameter an eine Methode übergeben, die von einem Objekt gehostet wird, auf das der Besitzer des Wegwerfobjekts alle Referenzen hält; das hostende Objekt wird das Wegwerfobjekt nicht verwenden, es sei denn, es wird dazu aufgefordert, und der Besitzer des Wegwerfobjekts wird wissen, ob er nie mehr solche Anfragen stellen wird.

Wenn eines dieser Muster auf Sie zutrifft, sind Sie möglicherweise in guter Verfassung. Wenn nicht, könnten Sie in Schwierigkeiten sein.

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