かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

Reactive Extensions入門 10「合成(SelectMany)」

さて、次はIQueryableから何かが通知されたら、それに応じた処理をしてIQueryableを返すという風にIQueryableを連鎖させるようなイメージの用途に使えるSelectManyメソッドを紹介します。
使い方は割と簡単で以下のように使えます。

var s = new Subject<int>();

// sから値が発行されたら0〜発行された値までのIQueryable<int>を返す
s.SelectMany(
    i => Observable.Range(0, i))
    .Subscribe(Console.WriteLine);
            
s.OnNext(1);
Console.WriteLine("----");
s.OnNext(2);
Console.WriteLine("----");
s.OnNext(3);

実行結果は、以下のようになります。

0
----
0
1
----
0
1
2

この例だとあまり有難味が感じ取れないかもしれませんが、クリックイベントが発行されたら、非同期でWebサービスを呼び出して、結果をUIに反映するといった処理の連鎖を書くときに使えます。コードのイメージとしては以下のようになります。

Observable.FromEvent<EventArgs>(button, "Click")
  .SelectMany(e => Observable.FromAsyncPattern<string>(hoge.BeginHoge, hoge.EndHoge)())
  .SubscribeOnDispatcher()
  .Subscribe(s => label.Text = s);

普通だと、クリックイベントハンドラの中でBeginHogeをして、コールバックメソッドを用意して、そこでUIスレッドにInvokeして値を更新!みたいなめんどくさいことしないといけないのが、すっきり書けるといった強みがあります。
これは素敵です。