過去記事インデックス
- Reactive Extensions再入門 その1
- Reactive Extensions再入門 その2「IObservableインターフェースとIObserverインターフェース」
- Reactive Extensions再入門 その3「IObservableのファクトリメソッド」
- Reactive Extensions再入門 その4「Timer系のファクトリメソッド」
- Reactive Extensions再入門 その5「HotとCold」
- Reactive Extensions再入門 その6「HotなIObservableを作成するファクトリ」
- Reactive Extensions再入門 その7「LINQスタイルの拡張メソッド」
- Reactive Extensions再入門 その8「SkipとTakeメソッド」
- Reactive Extensions再入門 その9「Skip + Take + Repeat = ドラッグ」
- Reactive Extensions再入門 その10「Doメソッド」
- Reactive Extensions再入門 その11「Catchメソッド」
- Reactive Extensions再入門 その12「Finallyメソッドとリソース解放」
- Reactive Extensions再入門 その13「最後の値を取得するLatestとMostRecentメソッド」
はじめに
今回は、前回やったLatestとMostRecentの仲間であるNextメソッドの紹介を行います。まず最初に、NextメソッドとLatestメソッドの挙動の違いを示すために必要なBehaviorSubject
BehaviorSubjectクラス
BehaviorSubject
// 初期値0のBehaviorSubject var behaviorSubject = new BehaviorSubject<int>(0); // 購読 Console.WriteLine("## Subscribe call"); behaviorSubject.Subscribe( i => Console.WriteLine("OnNext({0})", i), ex => Console.WriteLine("OnError({0})", ex.Message), () => Console.WriteLine("OnCompleted()")); // 順に値を発行して終了 Console.WriteLine("## OnNext(1) call"); behaviorSubject.OnNext(1); Console.WriteLine("## OnNext(2) call"); behaviorSubject.OnNext(2); Console.WriteLine("## OnNext(3) call"); behaviorSubject.OnNext(3); Console.WriteLine("## OnCompleted() call"); behaviorSubject.OnCompleted();
上記コードの実行結果を下記に示します。
## Subscribe call OnNext(0) <- ※Subscribeした時点でOnNextに通知がいってる ## OnNext(1) call OnNext(1) ## OnNext(2) call OnNext(2) ## OnNext(3) call OnNext(3) ## OnCompleted() call OnCompleted()
Subscribeをした時点で、コンストラクタで渡した初期値の0が通知されていることが確認できます。また、BehaviorSubject
// 初期値0のBehaviorSubject var behaviorSubject = new BehaviorSubject<int>(0); // 値を発行 Console.WriteLine("## OnNext(1) call"); behaviorSubject.OnNext(1); Console.WriteLine("Subscribe"); // 値を発行した後に購読開始 behaviorSubject.Subscribe( i => Console.WriteLine("OnNext({0})", i), () => Console.WriteLine("OnCompleted()")); behaviorSubject.OnCompleted(); // 終了した後に購読開始 Console.WriteLine("Subscribe"); behaviorSubject.Subscribe( i => Console.WriteLine("OnNext({0})", i), () => Console.WriteLine("OnCompleted()"));
実行結果を下記に示します。
## OnNext(1) call Subscribe OnNext(1) OnCompleted() Subscribe OnCompleted()
OnNext(1)を呼び出した後にSubscribeすると1が発行されていることが確認できます。また、OnCompleted()をしたあとにSubscribeするとOnCompletedが呼ばれていることが確認できます。
Nextメソッド
次に、LatestメソッドとMostRecentメソッドと同様にIObservable
// 初期値 -1のBehaviorSubject var s = new BehaviorSubject<int>(-1); // Latestの動作 Observable.Start(() => { Console.WriteLine("Latest start"); foreach (var i in s.Latest()) { Console.WriteLine("Latest : {0}", i); } }); // Nextの動作 Observable.Start(() => { Console.WriteLine("Next start"); foreach (var i in s.Next()) { Console.WriteLine("Next : {0}", i); } }); // 1秒間隔で値を発行する Observable.Start(() => { var i = 0; while (true) { Thread.Sleep(1000); Console.WriteLine("OnNext({0})", ++i); s.OnNext(i); } }); // 待機 Console.WriteLine("Please any key."); Console.ReadLine(); Console.WriteLine("End NextSample");
上記プログラムの実行結果を下記に示します。
Please any key. Latest start Next start Latest : -1 <- ※1 Latestは最後の値をキャッシュしているのでBehaviorSubjectの初期値-1を表示する OnNext(1) Next : 1 <- ※2 Nextは最後の値をキャッシュしないので1から表示する Latest : 1 OnNext(2) Next : 2 Latest : 2 OnNext(3) Next : 3 Latest : 3 OnNext(4) Latest : 4 Next : 4 End NextSample
※1の箇所にある通りLatestでは最後の値をキャッシュするためBehaviorSubjectの初期値である-1を表示しています。それに対してNextメソッドでは、初期値の-1は表示せずに1からの表示になっていることが確認できます。