VB.NET 11の新機能を最近知ったなど
さて、Yieldってなんだって話からですがこれはC#には2.0の時くらいからすでにあるyield returnの機能です
Yieldでyield returnが実行されます。yield breakはなさそう
ちょっと少し話が前後しますが最初に戻して進めます
・VB.NET 11での新機能
http://msdn.microsoft.com/en-US/library/we86c8x2.aspxを参照にしながら
書いてあるのは次の通りですね
・Async/Await
・Iterator/Yield
・呼び出し階層
・メソッド情報
・Global Namespaceのサポート
簡単なのはGlobal Namespaceですかね。これは今までルート名前空間に強制的に所属させられていたVB.NETですがGlobalを最初につけることでルート名前空間をつけなくて済みます
つまりSystem.linqに新しくクラス追加しようと思ったときいちいちルート名前空間をSystemにしなくてもGlobal.System.linqにすればいいわけです
メソッド情報は引数に属性をつけることで引数として現在の実行メソッド情報をとれる…?やつなんですかねぇ。これは分かりません
呼び出し階層はスタックトレースみたいのが取れるんじゃないかなぁと
Async/Awaitは非同期待機のやつですね。いくらでも書いてありそうなのでここではスルー
さて、最後にIterator/Yieldですがこれは反復子を指しますIteratorで宣言された関数はReturnの代わりにYieldで返す必要があります
・Iterator/Yield
ちゃんと見ていきます
[accessmodifier] Iterator (Function|Property)の戻り値はIEnumerable(Of T)またはIEnumerator(Of T)となります。(?)
またYieldは遅延実行することを示します。
Yieldは主にLINQで使われてたりするものです。つまるところ必要になるまでメソッドは実行されずに必要になったら評価されて実行されます。
少しコードを書いて試してみましょう
・yield returnの実行順序
次のようなソースコードを用意します。コンソールアプリケーションです
Private Iterator Function GetIterator(xcol As String) As IEnumerable(Of Char) For Each xch In xcol Yield xch Console.WriteLine("validation value") Next End Function Sub Main() Dim testArgs As IEnumerable(Of Char) = GetIterator("abcdefghijklmnopqr") For Each x In testArgs Console.WriteLine(x) Next Console.WriteLine("end test") End Sub
画像のとおり、yieldでリターンするとYield句まできた時点でメソッドはブロックされ、元の処理に戻されます。
そのためYieldの下のブロックは戻ってきたときにふたたび次のYieldまで実行されます
そのため上の画像のようにFor Each中に値の評価を行います。For Eachしたからといってすべてが一斉に返されないのも特徴といえるかもしれません
・Whereを実装してみる
yield return知りたいならLINQのWhereとか実装するといいといわれたので
自分でVB.NETでWhereを実装すると次のような感じです
Private Iterator Function myWhere(Of T)(source As IEnumerable(Of T), predicate As Func(Of T, Boolean)) As IEnumerable(Of T) For Each x As T In source If predicate(x) Then Yield x Next End Function
これで次のようなコードを実行してみます
Sub Main() Dim testArgs As IEnumerable(Of Integer) = Enumerable.Range(1, 200) For Each i In myWhere(testArgs, Function(x) x Mod 5 = 0) Console.WriteLine(i) Next Console.WriteLine("end test") End Sub
実行結果は…まあ普通のWhereの結果です
Selectは次のような感じでいいのかな?(テストできてない)
Private Iterator Function mySelect(Of T, TValue)(source As IEnumerable(Of T), predicate As Func(Of T, TValue)) As IEnumerable(Of TValue) For Each x As T In source Yield predicate(x) Next End Function
・どこで使うの
まあ基本はLINQみたいにコレクション操作になるとは思いますがYieldでやる必要がありなおかつLINQでサポートされてないメソッドというのがそんなにたくさん出てくるのか微妙な気は
そもそも.NET Framework 4.5なのでLINQでサポートしてる内容をわざわざYieldで使う必要ってないんですよね
LINQの理解のために使うとかLINQわからないからYield… くらい…?
それよりはやっぱりLINQとかでサポートしてないやつになるかなぁ…
結局使用方法が見いだせず…
というか前半の文面なんも考えてなかったせいでわかりづらいですね
とりあえずこの辺で
コメントを残す