.NET 2.0から新たにyieldというキーワードが追加されました。
これを利用すると、今までIEnumerableを実装していた部分を
ちょっと簡単にできます。
yieldが現れる以前は、IEnumerableとIEnumeratorインターフェースを実装する必要がありました。
ついでに、IEnumerableってどんな時に使うのかというと
自分で作ったコレクションクラスをイテレート可能、つまりforeachで
ループできるようにする場合です。
javaでいうと、イテレータを自分で作っているのと同じような感じです。
yieldの場合は、理屈よりもサンプルを見た方が分かりやすいです。
以下サンプルです。
イテレータの処理については、面倒なのでListクラスのものをそのまま
使ってます。
// vim:set ts=4 sw=4 et ws is nowrap ft=cs: using System; using System.Collections.Generic; namespace Gsf.Samples.CSharp{ ////// yield不使用版のカスタムコレクションクラスです。 /// /// Generic対応のIEnumerableを実装しています。 /// /// [実装の際の注意点] /// System.Collections.Generic.IEnumerableインターフェースは /// System.Collections.IEnumerableインターフェースを継承しています。 /// /// なので、genericの方のGetEnumerator()とnon-genericの方のGetEnumerator()の /// 両方を実装しないといけません。 /// class CustomCollection: IEnumerable { List _list; public CustomCollection(){ _list = new List (); } public CustomCollection AddRange(T values){ _list.AddRange(values); return this; } /// /// Genericな方のGetEnumeratorメソッド。 /// public IEnumeratorGetEnumerator(){ return _list.GetEnumerator(); } /// values){ _data.AddRange(values); return this; } ////// Genericじゃない方のGetEnumeratorメソッド。 /// System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator(){ return GetEnumerator(); } } ////// カスタムコレクションクラスです。 /// /// シンプルにイテレート可能なクラスを作成する方法であり、 /// yieldキーワードを使用してIEnumerableをimplementsせずにイテレート可能にします。 /// class CustomCollection4Yield{ List _data; public CustomCollection4Yield(){ _data = new List (); } public CustomCollection4Yield AddRange(T /// イテレータブロックです。 /// クラス内にこの書式のメソッドが存在している場合で、内部でyieldを使っている場合 /// コンパイラがコンパイル時に、IEnumeratorを自動作成してくれます。 /// public IEnumeratorGetEnumerator(){ foreach(T v in _data){ // // 呼び元にて、foreachを利用して本クラスをループしている // 場合、yieldがコールされると、現在の値を返し処理を中断。 // 呼び元が再び次の値を要求すると、処理が復帰し次の値を返す。 // (つまりコルーチン) // yield return v; } } } class YieldSample : IExecutable{ /// /// 以下のように戻り値をIEnumerableにし、内部で /// yieldを使う事もできる。 /// IEnumerableGetIterator(){ yield return "hoge"; yield return "hehe"; yield return "fuga"; } public void Execute(){ foreach(string v in GetIterator()){ Console.WriteLine(v); } foreach(string v in new CustomCollection ().AddRange(new string{"hoge", "hehe", "fuga"})){ Console.WriteLine(v); } foreach(string v in new CustomCollection4Yield ().AddRange(new string {"hoge", "hehe", "fuga"})){ Console.WriteLine(v); } } } }
補足:VisualBasicの場合は、yieldという構文が存在しないので、C#のようには出来ません。
直接、IEmumerable(Of T)を実装します。
Public Class Sample Implements IEnumerable(Of String) Private _list As New List(Of String)() Public Function GetEnumerator() As IEnumerator(Of String) Implements IEnumerable(Of String).GetEnumerator Return _list.GetEnumerator() End Function Private Function NonGenericGetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator Return GetEnumerator() End Function End Class