なぜIEnumerator< T> IDisposableを継承しますが、非ジェネリックIEnumeratorは継承しませんか?

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

  •  04-07-2019
  •  | 
  •  

質問

汎用の IEnumerator< T> はIDisposableを継承していますが、非汎用インターフェイスのIEnumeratorは継承していません。なぜこのように設計されているのですか?

通常、foreachステートメントを使用して IEnumerator< T> インスタンスを処理します。 foreachの生成されたコードには、実際に、最終的にDispose()を呼び出すtry-finallyブロックがあります。

役に立ちましたか?

解決

基本的には見落としでした。 C#1.0では、 foreach never Dispose 1 と呼ばれていました。 C#1.2(VS2003で導入-奇妙なことに1.1はありません) foreach は、イテレータが IDisposable を実装しているかどうかを finally ブロックでチェックし始めました-遡及的に IEnumerator IDisposable を拡張すると、すべての IEnumerator の実装が破損するため、彼らはそのようにしなければなりませんでした。 foreach がイテレータを最初に廃棄することが有用であると彼らが判断した場合、 IEnumerator IDisposable を拡張したはずです。 。

ただし、C#2.0と.NET 2.0が登場したとき、新しいインターフェース、新しい継承という新しい機会がありました。インターフェイスが IDisposable を拡張するようにすると、finallyブロックで実行時チェックが不要になり、コンパイラーはイテレーターが IEnumerator&lt ; T> は、 Dispose の無条件呼び出しを発行できます。

EDIT: Dispose が反復の終了時に呼び出されると、非常に便利です(ただし、終了します)。これは、イテレータがリソースを保持できることを意味します。これにより、イテレータは、たとえばファイルを1行ずつ読み取ることが可能になります。イテレータブロックは、「現在の実行ポイント」に関連する finally ブロックを確実にする Dispose 実装を生成します。イテレータは破棄されるときに実行されます。したがって、イテレータ内に通常のコードを記述でき、クリーンアップが適切に行われます。


1 1.0仕様を振り返ると、すでに指定されています。 1.0実装が Dispose を呼び出さなかったという以前の声明をまだ確認できていません。

他のヒント

IEnumerable< T> IDisposableを継承しません。 IEnumerator< T>ただし、IDisposableは継承しますが、非汎用IEnumeratorは継承しません。非ジェネリックIEnumerable(IEnumeratorを返す)に foreach を使用する場合でも、コンパイラはIDisposableのチェックを生成し、列挙子がインターフェイスを実装している場合はDispose()を呼び出します。

一般的な列挙子< T> IDisposableを継承するので、実行時の型チェックを行う必要はありません。先に進んで、Dispose()を呼び出すことができます。これは、列挙子に空のDispose( )メソッド。

これは古い議論ですが、ライブラリのユーザーがTのIEnumeratorを実装するだけのカスタムイテレータを実装できるTのT / IEnumeratorのIEnumerableを使用するライブラリを合理的に作成しました。

TのIEnumeratorがIDisposableを継承することは非常に奇妙であることがわかりました。管理されていないリソースを解放したい場合、IDisposableを実装しますか? IOストリームなど、アンマネージリソースを実際に保持する列挙子にのみ関係します。理にかなっている場合、列挙子にTのIEnumeratorとIDisposableの両方をユーザーに実装させないのはなぜですか。私の本では、これは単一の責任原則に違反しています-列挙子ロジックとオブジェクトの破棄を混在させる理由。

IEnumerable`はIDisposingを継承しますか? .NETリフレクターまたは MSDN によると。 IEnumerator と混同していないのですか? IDisposingは、コレクションを列挙するためだけに使用され、寿命を目的としないためです。

AndersH自身、または彼に近い人から応答を得ることができない限り、これについて明確にするのは少し難しい。

しかし、私の推測では、それは「収量」に関連していると思われます。 C#で同時に導入されたキーワード。 " yield return x"のときにコンパイラによって生成されたコードを見ると、を使用すると、IEnumeratorを実装するヘルパークラスにラップされたメソッドが表示されます。 IEnumeratorをIDisposableから派生させると、列挙が完了したときにクリーンアップできます。

IIRC IEnumerable< T> および IEnumerable を使用することについてのすべては、.Netのテンプレートに先行する IEnumerable の結果です。あなたの質問も同じように思われます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top