かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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して値を更新!みたいなめんどくさいことしないといけないのが、すっきり書けるといった強みがあります。
これは素敵です。