質問
yield ブロックを使用して実装する方法はありますか? IEnumerator<T>
これは後戻りできます (MoveLast()
)前方だけでなく?
解決
未直接イテレータブロックから、ノーます。
ただし、呼び出し側は常にList<T>
に例えば、結果をバッファリングするか、単にReverse()
呼び出すことができます - しかし、これは常に適用されません。
他のヒント
いいえ、C#コンパイラによって生成されたステートマシンが前方に厳密です。
それも、多くの場合、逆方向に行くことに意味がありません。ネットワークストリームからの読み込みイテレータを想像して - 後方に行くために、それは時間を巻き戻して再びデータのためのネットワークを頼むことができなかったので、それが今まで読んだすべてを覚えておく必要があります。
。 いくつかの非可逆方法でデータを生成し、(同上何でも各反復でコンウェイのライフのための新しいボードを返されたイテレータを想像して - 。すべてがそう、の1 の前のだったかもしれない複数のボードがありますあなたは再びあなたが既に返されてきたものを覚えておく必要が後方に移動します。)
私はこのスレッドは超古いです知っているが、それを注意することが適切である。
foreach(var item in someCollection)
{
// Do something
}
...にコンパイルされます:
var enumerator = someCollection.GetEnumerator()
while (enumerator.MoveNext())
{
var item = enumerator.Current;
// Do something
}
あなたがQUOT気にしないのであれば、<!>; <!> MoveNextメソッドQUOTを。構文は、簡単のIEnumeratorを実装し、QUOTを追加することができます。<!>; MovePreviousの各QUOT ;. <!> <!>; foreachのQUOT <!>あなたはQUOTを使用する場合の方向を逆にすることはできません。しかし、あなたは、whileループを使用した場合の方向を逆にすることができると思います。
それとも...あなたがしたい場合はQUOT <!>; <!> foreachのQUOT; (双方向ではない)逆方向のリストは、あなたがyield文を利用することができます。
public static IEnumerable<TItem> Get<TItem>(IList<TItem> list)
{
if (list == null)
yield break;
for (int i = list.Count - 1; i > -1; i--)
yield return list[i];
}
それとも、長いルートを行くことによって逆にforeachのしたい場合は...あなたはあなた自身のIEnumerable / IEnumeratorをを実装することができます。
public static class ReverseEnumerable
{
public static IEnumerable<TItem> Get<TItem>(IList<TItem> list)
{
return new ReverseEnumerable<TItem>(list);
}
}
public struct ReverseEnumerable<TItem> : IEnumerable<TItem>
{
private readonly IList<TItem> _list;
public ReverseEnumerable(IList<TItem> list)
{
this._list = list;
}
public IEnumerator<TItem> GetEnumerator()
{
if (this._list == null)
return Enumerable.Empty<TItem>().GetEnumerator();
return new ReverseEnumator<TItem>(this._list);
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
public struct ReverseEnumator<TItem> : IEnumerator<TItem>
{
private readonly IList<TItem> _list;
private int _currentIndex;
public ReverseEnumator(IList<TItem> list)
{
this._currentIndex = list.Count;
this._list = list;
}
public bool MoveNext()
{
if (--this._currentIndex > -1)
return true;
return false;
}
public void Reset()
{
this._currentIndex = -1;
}
public void Dispose() { }
public TItem Current
{
get
{
if (this._currentIndex < 0)
return default(TItem);
if (this._currentIndex >= this._list.Count)
return default(TItem);
return this._list[this._currentIndex];
}
}
object IEnumerator.Current
{
get { return this.Current; }
}
}
C5コレクションライブラリ( http://www.itu.dk/research/c5/) コレクションと後方の列挙とリンクリストを実装しています。あなたがそこに答えを見つけることができるはずですので、プロジェクトがオープンソースである。
はありません。 IEnumeratorの制限の1つは、それが現在の状態を保持し、それは、直前の状態を覚えていないということです。その結果、IEnumerableを前方のみである。
は、前の状態に保持するリストまたはLinkedListのにIEnumerableを読み、その代わりに、これらのオブジェクトを列挙する必要がある場合。
実際には、加速C#2008 に。残念ながら、2つのページがプレビューで表示されていない、それは反射に頼る必要がある(の結果はいつものように、キャッシュすることができる)ができますが、要点を取得することができます。
いいえ。使用する yield
結果は IEnumerable
それは一方向性です。