まあなんか書くことなかったんだけど笑 C#のyieldを目にする機会が多かったので、ちょっと調べてみました。Microsoftのドキュメントを読んでみると
ステートメントで yield キーワードを使用した場合、メソッド、演算子、または get アクセサーが反復子であることを示します。 yield を使用して反復子を定義すると、カスタム コレクション型の IEnumerable および IEnumerator パターンを実装するときに明示的な余分なクラス (列挙の状態を保持するクラス。たとえば IEnumerator
を参照) が不要になります。
フーン
まあコード書いてこのyieldの利益をえてみましょう。まずyieldを使っていない書き方から
class YieldTest { static void Main(String[] args) { foreach (var item in GenDataset()) { Console.WriteLine(item); } } static List<String> GenDataset() { List<String> dataset = new List<String>(); for (int i = 0; i < 100; i++) { dataset.Add(i.ToString()); } return dataset; } }
まあ単純に0から99までの数字を配列に入れているだけです。次にyieldを使った書き方に変更してみます
class YieldTest { static void Main(String[] args) { var dataSet = GenDataset(); foreach (var item in dataSet) { Console.WriteLine(item); } } static IEnumerable<String> GenDataset() { for (int i = 0; i < 100; i++) { yield return i.ToString(); } } }
ListからIEnumerableというインターフェースに変更して、かつ内部のListの変数宣言などが不要になっています
正直この例だと簡単過ぎてメリットを感じないのですが笑
ここでメソッドから帰ってきた配列の型を確認してみましょう。普通に書いた方は
System.Collections.Generic.List
1[System.String]`
ですが、yieldで書いた方は
YieldTest+<GenDataset>c__Iterator0
という形で返ってきています。イテレータとなっていることから、List型ではなく、反復子として処理されたことがわかります。なので、内容はList型のような参照を行うことが出来ません(配列要素をカウントするCountなどをメソッドチェインすることは不能です)
。。結論として何を言いたいんだって感じになってしまいましたが、まあRubyにもYieldあったなあって思って色々試しただけですw
久しぶりにまとまらない話になりましたorz