Warum IEnumerator von IDisposable erbt, während der nicht-generische IEnumerator nicht?

StackOverflow https://stackoverflow.com/questions/232558

  •  04-07-2019
  •  | 
  •  

Frage

Ich habe bemerkt, dass der generische IEnumerator<T> von IDisposable erbt, aber die nicht-generische Schnittstelle IEnumerator nicht. Warum ist es auf diese Weise gestaltet?

Normalerweise verwenden wir foreach-Anweisung durch eine IEnumerator<T> Instanz zu gehen. Der generierte Code von foreach hat tatsächlich versuchen-finally-Block, der in schließlich Dispose () aufruft.

War es hilfreich?

Lösung

Im Grunde war es ein Versehen. In C # 1.0, foreach nie genannt Dispose 1 . Mit C # 1.2 (in VS2003 eingeführt - es gibt keine 1.1, bizarr) foreach im finally Block zu prüfen begann, ob der Iterator implementiert IDisposable - sie es auf diese Weise zu tun hatte, weil nachträglich IEnumerator IDisposable verlängern machen würde gebrochen Umsetzung der alle haben von IEnumerator. Wenn sie heraus gearbeitet haben, dass es nützlich ist für foreach von Iteratoren an erster Stelle zu entsorgen, ich bin sicher, dass IEnumerator würde IDisposable erweitert hat.

Wenn C # 2.0 und .NET 2.0 herauskommt, aber sie hatten eine neue Chance - neue Schnittstelle, neue Vererbung. Es macht viel mehr Sinn die Schnittstelle zu haben IDisposable zu erweitern, so dass Sie nicht eine Ausführungszeitprüfung im finally-Block brauchen, und jetzt der Compiler weiß, dass, wenn der Iterator ein IEnumerator<T> ist, kann es einen unbedingten Aufruf emittieren Dispose.

EDIT: Es ist unglaublich nützlich für Dispose am Ende der Iteration aufgerufen werden (aber es endet). Es bedeutet, dass der Iterator auf Ressourcen festhalten kann - was es möglich macht, dafür zu, sagen wir, eine Datei Zeile für Zeile lesen. Iterator Blöcke erzeugen Dispose Implementierungen, die sicherstellen, dass alle finally Blöcke relevant für den „aktuellen Punkt der Ausführung“ des Iterators ausgeführt werden, wenn sie entsorgt wird -. So können Sie normalen Code innerhalb des Iterator und clean-up sollte in geeigneter Weise geschehen schreiben


1 Rückblick auf die 1.0-Spezifikation, es wurde bereits festgelegt. Ich habe noch nicht gelungen, diese frühere Aussage zu verifizieren, dass die 1.0 Implementierung nicht Dispose angerufen hat.

Andere Tipps

IEnumerable erben nicht IDisposable. IEnumerator erbt IDisposable jedoch, während der nicht-generische IEnumerator nicht. Selbst wenn Sie foreach für eine nicht-generische IEnumerable (die gibt IEnumerator), wird der Compiler noch einen Scheck für IDisposable erzeugen und rufen Sie Dispose (), wenn der Enumerator die Schnittstelle implementiert.

Ich denke, die allgemeine Enumerator von IDisposable erbt, so gibt es keine Laufzeittyp-Check-it nur sein muss kann voran gehen und rufen Sie Dispose (), die eine bessere Leistung haben sollte, da es wahrscheinlich optimiert werden kann weg, wenn der Enumerator eine leere Methode Dispose () hat.

Ich weiß, dass dies eine alte Diskussion, aber ich schrieb reasontly eine Bibliothek, wo ich IEnumerable von T / IEnumerator von T verwendet, in denen Benutzer der Bibliothek können auch eigene Iteratoren implementieren sollten sie nur IEnumerator von T implementieren.

Ich fand es sehr merkwürdig, dass IEnumerator von T von IDisposable erben würde. Wir implementieren IDisposable, wenn wir unmanged Ressourcen richtig befreien wollen? So wäre es nur für Enumeratoren relevant sein, die tatsächlich nicht verwalteten Ressourcen halten - wie ein IO-Stream usw. Warum nicht nur Benutzer lassen sowohl IEnumerator von T und IDisposable auf ihrem enumerator implementieren, wenn es Sinn macht? In meinem Buch verletzt dies die einzige Verantwortung Prinzip - Warum enumerator Logik und Entsorgung Objekte mischen.

Hat IEnumerable` IDisposing erben? Gemäß dem Reflektor oder .NET MSDN . Sind Sie sicher, dass Sie verwirren nicht mit IEnumerator ? Das nutzt IDisposing, weil es nur für eine Sammlung aufzählt und nicht für Langlebigkeit gemeint.

Ein bisschen hart daran endgültig zu sein, es sei denn Sie eine Antwort von Andersh selbst oder jemand nah an ihm bekommen verwalten.

Aber meine Vermutung ist, dass es auf die „Ausbeute“ Schlüsselwort bezieht, die in C # zur gleichen Zeit eingeführt wurde. Wenn Sie die vom Compiler erzeugten Code zu buchen, wenn „yield return x“ verwendet wird, müssen Sie die Methode sehen in einer Hilfsklasse eingewickelt, die IEnumerator implementiert; IEnumerator von IDisposable absteigen, die sicherstellt, dass es aufzuräumen kann, wenn Enumeration abgeschlossen ist.

IIRC Das Ganze über IEnumerable<T> und IEnumerable hat, ist ein Ergebnis der IEnumerable .Net Vorlage Zeug datierend. Ich vermute, dass Ihre Frage in der gleichen Art und Weise ist.

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