C # IDverfügbare Frage

8

Ich habe das folgende Codebeispiel:

%Vor%

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

Ich möchte nicht, dass die IRepository -Schnittstelle IDisposable implementiert, weil das zu unerwünschter Komplexität und einer Menge von Klassen führen würde, die auch IDisposable implementieren müssten.

Wie soll dieser Fall behandelt werden?

Ich bin mir sicher, dass dies in jeder Typhierarchie vorkommen kann - wenn einer der abgeleiteten Typen verfügbare Ressourcen verwalten muss.

Also, was soll ich tun - ziehen Sie IDisposable bis zur allerersten Schnittstelle hoch oder lassen Sie es so, und ich hoffe, der Benutzer würde Einweg- und Nicht-Wegwerf-Repositories unterscheiden.

Danke.

    
Yippie-Ki-Yay 13.12.2010, 17:01
quelle

6 Antworten

3

Was Sie beschrieben haben, ist mit einem wichtigen Vorbehalt in Ordnung: 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 der Eigentümer eines IDisposable-Objekts (*) entweder dafür sorgen, dass das Objekt selbst entsorgt wird, oder das Objekt an einen neuen Eigentümer übergeben, der die Verantwortung übernehmen und respektieren kann. Anfänglich sind IDisposable-Objekte im Allgemeinen ihrem Ersteller "gehört", aber Handoffs sind üblich. Ein Verweis auf ein IDisportierbares Objekt kann einem anderen Objekt übergeben werden, ohne das Eigentum zu übertragen; In diesem Szenario ist der Besitzer immer noch dafür verantwortlich, das Objekt zu entsorgen, wenn es nicht mehr benötigt wird. Dazu muss der Besitzer wissen, dass das Objekt nicht mehr benötigt wird. Die häufigsten Muster sind:

  1. Das Objekt wird als Parameter an eine Methode übergeben; Das Objekt, das die Methode hostet, verwendet das Objekt nicht, nachdem die Methode zurückgegeben wurde.
  2. Das Objekt wird als Parameter an eine Methode übergeben, die es in einem Objektfeld speichert, aber dieses Objekt kann später irgendwie aufgefordert werden, die Referenz zu zerstören.
  3. Das Disposable wird als Parameter an eine Methode übergeben, die von einem Objekt gehostet wird, auf dem der Eigentümer des Einwegobjekts alle Referenzen hält; Das Hosting-Objekt wird das Einwegobjekt nur dann verwenden, wenn es angefordert wird, und der Eigentümer des Einwegobjekts weiß, ob es nie mehr solche Anfragen ausgeben wird.

Wenn eines dieser Muster zutrifft, können Sie in guter Verfassung sein. Wenn nicht, könntest du in Schwierigkeiten sein.

    
supercat 13.12.2010, 18:59
quelle
15

Ja, ich würde sagen, das ist schlecht - weil Sie nicht alle Repositories auf die gleiche Weise verwenden können.

Ich würde persönlich die Repository-Schnittstelle erweitern IDisposable - es ist einfach genug, um es schließlich mit einem No-Op implementieren.

Dies ist genau die selbe Wahl, wie sie von Stream , TextReader und TextWriter im Hauptrahmen gemacht wird. StringWriter (zum Beispiel) muss nichts loswerden ... aber TextWriter ist immer noch verfügbar.

Das kommt daher, weil IDisposable in gewisser Weise eine seltsame Schnittstelle ist: Es vermittelt nicht etwas, das den Anrufern angeboten wird ... es vermittelt etwas, das erforderlich ist von Anrufern (oder zumindest, stark ermutigt mit möglichen Problemen, wenn Sie nicht mitmachen).

    
Jon Skeet 13.12.2010 17:16
quelle
9

Das einzige Problem, das Sie möglicherweise haben, ist, wenn Sie eine Art von Factory, Inversion of Control oder Dependency Injection pattern / framework verwenden. Wenn Sie das Objekt als Schnittstelle verwenden möchten, können Sie dies nie tun:

%Vor%

Sie möchten vielleicht ein INHibernateRepository vorstellen, das IDisposable implementiert. Da IDisposable normalerweise eine solche Operation auf niedriger Ebene ist, gibt es kein großes Problem damit, dass Ihre Schnittstellen diese Schnittstelle implementieren.

    
poindexter12 13.12.2010 17:11
quelle
4

Nein, ziehe das IDisposable nicht hoch. Halten Sie die Schnittstellen atomar, einfach und unabhängig.

Wenn Sie nicht argumentieren können, dass IDisposable ein fundamentales Merkmal des IRepository ist (und SampleRepository zeigt, dass dies nicht der Fall ist), sollte es keine Ableitung zwischen den beiden geben.

    
Henk Holterman 13.12.2010 17:05
quelle
3

Das scheint mir vollkommen in Ordnung zu sein. Was ist das Problem?

    
Matt Lacey 13.12.2010 17:04
quelle
2

Erstens, um Ihre Frage zu beantworten. Das Dispo-Muster unterscheidet sich von einem C ++ - Destruktor. Eine Dispose -Methode soll die Ressourcen der Klasse beseitigen, anstatt die -Klasse selbst zu entfernen .

Der Grund für das Markieren von C ++ - Destruktoren als virtual ist in .NET nicht vorhanden, da jede Instanz eines Referenztyps einen Sync-Block enthält, der Informationen zum Laufzeittyp enthält. Auf diese Weise kann der Garbage Collector die korrekte Speichermenge entsprechend wiederherstellen.

Wie man IRepository mit IDisposable erweitert, wäre das 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 alle abgeleiteten Klassen erfordert, um die Schnittstelle zu implementieren. Auf den ersten Blick scheint es einfach zu sein, eine Schnittstelle mit NOPs zu implementieren (vielleicht mehrere Male), aber das sollte nicht sein müssen. Aber ich kann eine Alternative anbieten.

Verwenden Sie stattdessen eine abstrakte Basisklasse, die das Dispose-Muster implementiert. Dies würde der Struktur der "Standard" -Implementierung des Verfügungsmusters folgen.

%Vor%

Werfen Sie einen Blick auf die Anleitung zum Löschen von Mustern , die von Microsoft geschrieben wurden, um ein detaillierteres Beispiel zu sehen .

    
Matt Brunell 13.12.2010 18:31
quelle

Tags und Links