GetEnumerator() メソッドが IEnumerator から除外されて IEnumerable に配置された理由が気になりました。すべての列挙子メソッドを IEnumerator に保持する方が理にかなっているように思えます。
ありがとう、
スコット
GetEnumerator() メソッドが IEnumerator から除外されて IEnumerable に配置された理由が気になりました。すべての列挙子メソッドを IEnumerator に保持する方が理にかなっているように思えます。
ありがとう、
スコット
「これが本当かどうか想像してみてください」と自問してください。
すべての列挙メソッドが 1 つのインターフェイス上にある場合、2 人の呼び出し元が同じリストを同時に列挙するにはどうすればよいでしょうか?
1 つは「あなたは私を列挙できます」と言い、もう 1 つは「特定の列挙タスクを追跡するオブジェクトです」と言うため、2 つのインターフェイスがあります。
IEnumerable
インターフェイスは、必要な数のオブジェクトを作成するファクトリですIEnumerator
。これらの列挙子をいつどのように使用するかは、消費者次第です。
IEnumerable
オブジェクトが、線形に反復できるデータのコレクションまたはソースであることを意味します。IEnumerator
反復を実行する実際の実装のインターフェースです。
「IEnumerable」は「来て、私を列挙してください」と言っているため(そして、あなたはどうやって列挙子をくれますか)、「IEnumerator」は「あなたのコレクションを列挙できます!」と言っているからです。すでに持っているので、もう入手する必要はありません。
ここで非常に良い答えが得られました。ちょっとだけ強調。列挙子は状態を保持し、列挙されているコレクション内の現在のオブジェクトを追跡します。IEnumerator.Current から利用できます。そして、IEnumerator.MoveNext() という状態を変更する方法を知っています。状態を保持するには、状態を格納する別のオブジェクトが必要です。コレクション オブジェクトは 1 つしかありませんが、複数の列挙子が存在する可能性があるため、その状態をコレクション オブジェクト内に簡単に格納することはできません。
コレクションがその列挙子を追跡することは実際に可能であるため、「簡単に」というフレーズを使用しました。結局、反復子を返すのは、コレクション クラスの GetEnumerator() メソッドへの呼び出しでした。これを行う .NET フレームワークには、Microsoft.VisualBasic.Collection という 1 つのコレクション クラスがあります。Collection クラスの VB6 コントラクトを実装する必要があり、そのコントラクトは、コレクションが列挙されている間にコレクションを変更することが合法であることを指定しています。つまり、コレクションが変更された場合、作成されたすべてのイテレータ オブジェクトを適切に処理する必要があります。
彼らはかなり良いトリックを思いつきました.WeakReferenceはこれに触発されたのかもしれません. Reflector が示すコードを見てください。刺激的なもの。さらに掘り下げて、コレクションクラスで「バージョン」を見つけます。すごいトリック。
minlinqに関する Bart De Smet の投稿を読んだ後、2 つのインターフェイスを分割することが厳密に必要であるとは確信できなくなりました。
たとえば、上記のリンクでは、IEnumerable/IEnumerator が単一のメソッド インターフェイスに折りたたまれています。
Func<Func<Option<T>>>
およびいくつかの基本的な実装
public static class FEnumerable
{
public static Func<Func<Option<T>>> Empty<T>()
{
return () => () => new Option<T>.None();
}
public static Func<Func<Option<T>>> Return<T>(T value)
{
return () =>
{
int i = 0;
return () =>
i++ == 0
? (Option<T>)new Option<T>.Some(value)
: (Option<T>)new Option<T>.None();
};
}
...
}
public static Func<Func<Option<T>>> Where<T>(this Func<Func<Option<T>>> source, Func<T, bool> filter)
{
return source.Bind(t => filter(t) ? FEnumerable.Return(t) : FEnumerable.Empty<T>());
}
多くの場合、列挙を行っていることは、列挙されていることと接線方向にのみ関連しているからです。IEnumerable と IEnumerator が同じインターフェイスである場合、それらを共有することはできませんでした。または、GetEnumerator に、列挙するオブジェクトを渡すことができる型指定されていない引数が必要です。それらを分割すると、列挙インフラストラクチャを異なるタイプ間で共有できる可能性があります。