Warum sollte ich IDisposable anstatt in c#?
Heute, ich wollte zu einer operation mit einer Datei, so kam ich mit diesem code
class Test1
{
Test1()
{
using (var fileStream = new FileStream("c:\\test.txt", FileMode.Open))
{
//just use this filestream in a using Statement and release it after use.
}
}
}
Aber auf code-review, wurde ich gebeten, zu implementieren IDisposable-Schnittstelle und Finalizer-Methoden
class Test : IDisposable
{
Test()
{
//using some un managed resources like files or database connections.
}
~Test()
{
//since .NET garbage collector, does not call Dispose method, i call in Finalize method since .net garbage collector calls this
}
public void Dispose()
{
//release my files or database connections
}
}
Aber, meine Frage ist, warum sollte ich ?
Obwohl ich nicht rechtfertigen, meine Methodik nach mir, warum sollten wir IDisposable wenn mit - Anweisung kann sich die Freigabe von Ressourcen)
Irgendwelche speziellen Vorteile oder bin ist hier etwas fehlt?
Sollten Sie nur hinzufügen, einen finalizer, wenn Sie nicht verwaltete Ressourcen, die bereinigt werden sollen. Ein
FileStream
ist ein managed Ressource.InformationsquelleAutor now he who must not be named. | 2013-09-02
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Antwort "Keine" ist richtig, dass
using
block kann nur verwendet werden, für die Klassen implementieren dieIDisposable
- Schnittstelle und eine Erklärung, es ist perfekt. Die Frage von Ihrer Seite ist", Warum muss ich hinzufügen IDisposable auf die Test-Klasse und Aber auf code-review, wurde ich gebeten, zu implementieren IDisposable-Schnittstelle und Finalizer-Methoden auf die Test-Klasse."Die Antwort ist einfach
1) Als die pro, die coding-standards, gefolgt von so viele Entwickler ist es immer gut zu implementieren
IDisposable
auf die Klassen, die einige Mittel und, wenn der Bereich des Objekts ist über die Dispose-Methode in dieser Klasse wird sicherstellen, dass alle Ressourcen freigegeben worden sind.2) die Klasse, Die geschrieben wurde, ist nie so, dass in Zukunft keine änderungen vorgenommen werden und wenn änderungen vorgenommen werden und neue Ressourcen Hinzugefügt werden, dann der Entwickler weiß, dass er zur Freigabe dieser Ressourcen in der Dispose-Funktion.
Aber Dmitri wir immer Beratung Entwickler IDisposable-Klassen, die einige umfangreiche Ressourcen.
gute explananation. danke. +1
Technisch ist dies eine Antwort, aber "future changes" ist eine schreckliche Grund. Es sei denn, Sie haben spezifische Funktionen im Hinterkopf, dass Sie ziemlich sicher umgesetzt werden, gibt es keinen Grund eine Klasse IDisposable implementieren, es sei denn, es muss. Selbst dann haben Sie zu sein in einer situation, wo Sie nicht ändern können, die Schnittstelle der Klasse, aber eine änderung die Umsetzung ist nicht zu brechen ändern.
Die person, die mit Ihrer Klasse davon ausgehen, dass nicht verwalteten Ressourcen, wenn es verwendet, die IDisposable-Schnittstelle. Sie haben dann, um jegliche beifügen Objekt Ihrer Klasse im "using" - Anweisung (oder die dispose-Methode aufrufen), um sicherzustellen, dass Ihr code nicht undicht nicht verwaltete Ressourcen. Wenn jeder Tat dies, unabhängig von der Verwendung nicht verwalteter Ressourcen oder nicht, alle Instanziierungen von Klassen werden müsste enlosed in der "using" - Anweisungen. Es ist wirklich eine gute Idee, zu Lügen, um die Benutzer Ihrer Klasse, und sagen Sie Ihnen, dass Ihre Klasse verwendet nicht verwalteten Ressourcen, wenn es nicht an???
InformationsquelleAutor dbw
in deinem Beispiel mit Erklärung richtig ist, weil man Ressourcen nur im Umfang Ihrer Methode. Zum Beispiel:
aber wenn die Ressourcen eingesetzt werden, die außerhalb einer Methode, dann sollten Sie Dispose-Methode.
Dieser code ist falsch:
Die richtige Sache zu tun ist, implementieren
IDisposable
um sicher zu sein, dass die Datei veröffentlicht wird, nachdem es verwendet wird.Diese Antwort ist besser als das akzeptiert man.
InformationsquelleAutor Dmitry Dovgopoly
Einen kleinen Hinweis erst, seit Sie scheinen ein wenig verwirrt darüber, wie
using
undIDisposable
miteinander interagieren: Der Grund, warum Sie in der Lage zu sagenusing (FileStream fileStream = Whatever()) { ... }
gerade weil dieFileStream
Klasse implementiertIDisposable
. Was Ihre Kollegen vorgeschlagen haben ist, dass Sie implementierenIDisposable
auf Ihre Klasse, so dass Sie in der Lage sein zu sagenusing (Test test = new Test()) { ... }
.Für was es Wert ist, ich denke, die Art und Weise Sie schrieb den code zunächst ist es dringend vorzuziehen, um die vorgeschlagene änderung, es sei denn, es gibt einige zwingende Gründe, warum möchten Sie vielleicht zu halten, die
FileStream
offen für die gesamte Lebensdauer einesTest1
Instanz. Ein Grund, warum dies der Fall ist, die Datei könnte sich ändern von einer anderen Quelle nach der Konstruktor derTest1
genannt worden ist, in welchem Fall Sie stecken mit eine ältere Kopie der Daten. Ein weiterer Grund für die Beibehaltung derFileStream
offen sein könnte, wenn Sie ausdrücklich möchten, sperren Sie die Datei aus, auf die geschrieben wird aus, während anderswo einTest1
Objekt ist lebendig.Im Allgemeinen, es ist gute Praxis, die Freigabe von Ressourcen, so bald wie möglich, die ursprünglichen code scheint zu tun. Eine Sache, die ich bin ein wenig skeptisch ist, dass die Arbeit getan wird, im Konstruktor, anstatt in irgendeine Methode, die explizit genannt von außen (Erklärung: http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/). Aber das ist eine ganz andere Sache, und unabhängig von der Frage, ob Sie Ihre Klasse implementieren
IDisposable
.Ich denke, diese Antwort ist viel besser als die akzeptiert, die finde ich eigentlich verwirrend.
InformationsquelleAutor Magnus Grindal Bakken
Basierend auf den Informationen, die Sie zur Verfügung gestellt, es gibt absolut keinen Grund zu implementieren
IDisposable
oder einen finalizer aufTest
.Nur einen finalizer implementieren zu release nicht verwaltete Ressourcen (window handle GDI-handle-Datei-handle). Sie in der Regel nicht haben, um jemals tun, es sei denn, Sie sind PInvoking die Win32 API oder etwas. Microsoft hat freundlicherweise gewickelt, dies für Sie in der
FileStream
so dass Sie nicht haben, um sorgen über Datei-handles.Einen finalizer gemeint ist, zu bereinigen nicht verwalteter Ressourcen, wenn ein Objekt bei der Speicherbereinigung.
Da der garbage collector kann es sehr lange dauern, bevor Sie entscheidet, um zu erfassen Ihr Objekt, möchten Sie vielleicht einen Weg, um die trigger-Bereinigung. Nein,
GC.Collect()
ist nicht der richtige Weg, das zu tun. 😉Frühzeitiges Bereinigung der systemeigenen Ressourcen, ohne zu warten, für den garbage collector implementieren Sie
IDisposable
auf Ihre Klasse. Damit können sich die Anrufer trigger cleanup-ohne warten auf der GC. Dies gilt nicht führen, dass Ihr Objekt, befreit zu werden von der GC. Alle es tut, ist frei, die einheimische Ressource.In dem Fall, wo ein Objekt besitzt ein anderes Objekt, das ist Einweg, dann die besitzenden Objekts implementieren auch
IDisposable
und rufen Sie einfach die anderen ObjektsDispose()
.Beispiel:
Beachten Sie, dass
Tree
nicht der finalizer. Es implementiertDispose
denn es muss Pflege überApple
Aufräumen.Apple
einen finalizer hat, um sicherzustellen, dass es reinigt dasCore
Ressource.Apple
ermöglicht die frühzeitige Bereinigung durch den AufrufDispose()
Dem Grund, dass Sie nicht brauchen
Dispose
und sicherlich nicht finalizer ist, weil Ihre KlasseTest
besitzt keine eigenen member-Bereich, die nicht oderIDisposable
. Sie passieren, um erstellen Sie eineFileStream
, was ist Einweg, aber Sie reinigen sich vor dem verlassen der Methode. Es ist nicht im Besitz derTest
Objekt.Es gibt eine Ausnahme zu diesem Fall. Wenn Sie eine Klasse zu schreiben, die Sie kennen, werden geerbt, von anderen, und die anderen können umsetzen
IDisposable
, dann sollten Sie voran gehen und implementierenIDisposable
. Andernfalls wird der Anrufer wird nicht wissen, zu entsorgen, das Objekt (oder sogar in der Lage sein, ohne Gießen). Dies ist jedoch ein code smell. Normalerweise würden Sie nicht von einer Klasse Erben, und fügen SieIDisposable
. Wenn Sie das tun, wahrscheinlich ist es schlechtes design.(wird fortgesetzt...) diese Beiden Unterklassen hinzufügen sollte, IDisposable unterstützen, aber die Basis-Einstellungen-Klasse sollte nicht. Warum nicht? Betrachten Sie eine weitere Ressource namens SomeOtherSettings, der nicht verwaltete Ressourcen. Wenn Sie die Kraft der Basis-Klasse implementiert IDisposable, Sie haben jetzt gesagt, SomeOtherSettings, dass Sie brauchen, um über die Entsorgung von etwas, das heißt, Sie auch jetzt müssen, zu unterstützen IDisposable. Sie haben einfach nur gestunken, bis die code-Hierarchie. Sehen, was ich meine? Das ist für mich der echte Geruch.
ja es stinkt zum hinzufügen
IDisposable
aber es ist nicht wirklich vermeidbar. Dies ist aufgrund der Liskov-Substitution-Prinzip. Wenn Sie eineSettings
Basisklasse, dann alle Verbraucher-wer erkennt Objekte des TypsSettings
muss auch akzeptieren, Objekte vom TypFileSettings
. Nun, wenn dieFileSettings
Klasse erfordert eine Bereinigung, wie werden die Verbraucher wissen sollte? Das ist, warum ich erwähnte die Typumwandlung in diesem Punkt. WennSettings
Unterklassen kann implementierenIDisposable
, so ist jeder Verbraucher, der im Besitz einerSettings
Objekt muss immer prüfen, ob das Objekt wirft, umIDisposable
.Beim design der
Settings
Basis-Klasse, die Sie definiert haben, den Vertrag der Klasse. Jede Methode ist eine Funktion der Klasse.IDisposable
ist besonders, es kommuniziert auch Aufgaben des aufrufenden Codes. Es ist riskant, in neue Verantwortlichkeiten für die Anrufer, die in den Unterklassen, weil dann jeder, der arbeitet aufSettings
Objekte hat auf Magische Weise das wissen über diese möglichen Verantwortung von einigen Unterklassen. Es ist am sichersten, nur um hinzuzufügen, dass die Verantwortung in den Vertrag von der Basis-Klasse, so vermeiden Sie überraschende Verbraucher.Ich würde argumentieren, dass, wenn die Entsorgung ist nicht Bestandteil der Basis-Klasse in der Verantwortung, als irgendwo, das dauert, die Basis-Klasse der sollte nicht kennen, weil es nicht Teil des Vertrages, perfekt folgenden Liskov-Prinzip. Der Schöpfer der Unterklasse, jedoch sollte und würde, denn Sie wäre die Erstellung einer Instanz der FileSettings. Das ist, warum ich ein bisschen zu bleiben mit meiner ursprünglichen Aussage es mehr stinkt, als nicht. Nach allem, wie kann ich wissen, wer der Unterklasse Einstellungen und was Sie hinzufügen können? Sollte ich werfe jede mögliche Sache? Nein. Also, warum ist IDisposable anders?
InformationsquelleAutor dss539
Kurze Antwort ist, dass jede Klasse, die nicht implementieren IDisposable verwendet werden kann, verwenden.
Nein, es ist nicht frei, Ressourcen selbst.
Wie ich oben schrieb, dass Sie brauchen, um zu implementieren IDisposable inorder, um in der Lage sein zu verwenden verwenden. Nun, wenn Sie IDisposable implementieren Sie erhalten eine Dispose-Methode. Bei dieser Methode schreiben Sie den code, der sollte sich darum kümmern, alle Ressourcen, die entsorgt werden muss aus-wenn das Objekt nicht mehr benötigt wird.
Der Zweck der VERWENDUNG ist, dass, wenn ein Objekt geht aus dem Rahmen, wird die dispose-Methode aufrufen und das ist es.
Beispiel
übersetzen zu
Sie verwendet haben, mit auf die FileStream-Klasse. nicht auf Test1 Klasse.
Sie sind mit der "Verwendung" für die FileStream-aber Sie werden nicht in der Lage zu verwenden, "mit" für die Klasse. Also ich denke, die Beurteilung gemeint, dass Sie sollten implementieren IDisposable für die Klasse Test1, um der Lage sein, zu schreiben: mit(Test1 t = new Test1())
Da bist du mit 'mit' auf FileStream und nicht auf Test1
Sie können nicht dies tun, indem Sie(Test1 t = new Test1()) {}
InformationsquelleAutor Ehsan
Ich denke, die Frage ist eher wie "Soll ich entsorgen Sie die Datei sofort oder mit der Dispose-Methode der Klasse, die die Zugriffe auf diese Datei?"
Hängt es: wenn Sie den Zugriff auf die Datei nur im Konstruktor meiner Meinung nach gibt es keinen Grund für die Implementierung von der IDisposable. Mit ist der richtige Weg,
Sonst, wenn Sie die gleiche Datei auch in anderen Methoden, vielleicht ist es eine gute übung öffnen Sie die Datei einmal und schließen Sie es in Ihrer Dispose-Methode (Implementierung der IDisposable -)
InformationsquelleAutor Emanuele