過去記事インデックス
- 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メソッドとリソース解放」
はじめに
今回は、これまでにないタイプのメソッドについて説明します。IObservable
Latestメソッド
ここでは、Latestメソッドについて説明します。LatestメソッドはIObservable
// 値の発行元 var s = new Subject<int>(); // Latestで取得したIEnumerable<int>の値を印字 Observable.Start(() => { Console.WriteLine("Start latest loop"); foreach (var i in s.Latest()) { Console.WriteLine("LatestValue : {0}", i); } Console.WriteLine("End latest loop"); }); // 1秒間隔で値1〜10の値を発行 Observable.Start(() => { foreach (var i in Enumerable.Range(1, 10)) { Thread.Sleep(1000); Console.WriteLine("OnNext({0})", i); s.OnNext(i); } Console.WriteLine("OnCompleted()"); s.OnCompleted(); }); // 終了しないため待つ Console.ReadLine();
実行結果を下記に示します。
Start latest loop OnNext(1) LatestValue : 1 OnNext(2) LatestValue : 2 OnNext(3) LatestValue : 3 OnNext(4) LatestValue : 4 OnNext(5) LatestValue : 5 OnNext(6) LatestValue : 6 OnNext(7) LatestValue : 7 OnNext(8) LatestValue : 8 OnNext(9) LatestValue : 9 OnNext(10) OnCompleted() LatestValue : 10 End latest loop
動作結果から、OnNextで値が発行された後に、Latestで取得したIEnumerable
今回の例では、値の発行とLatestで変換したIEnumerable
// 値の発行元 var s = new Subject<int>(); // Latestで変換したIEnumerableからIEnumeratorを取得 var e = s.Latest().GetEnumerator(); // 1を発行してIEnumeratorから値を取得 Console.WriteLine("OnNext(1)"); s.OnNext(1); Console.WriteLine("MoveNext : {0}", e.MoveNext()); Console.WriteLine("Current : {0}", e.Current); // 10と100を発行してIEnumeratorから値を取得 Console.WriteLine("OnNext(10)"); s.OnNext(10); Console.WriteLine("OnNext(100)"); s.OnNext(100); Console.WriteLine("MoveNext : {0}", e.MoveNext()); Console.WriteLine("Current : {0}", e.Current); // IObservable<T>のシーケンスを終了したMoveNextを呼んでみる Console.WriteLine("OnCompleted()"); s.OnCompleted(); Console.WriteLine("MoveNext : {0}", e.MoveNext());
実行結果を下記に示します。
OnNext(1) MoveNext : True Current : 1 OnNext(10) ← ※1 OnNext(100) ← ※2 MoveNext : True Current : 100 ← ※3 OnCompleted() MoveNext : False
実行結果の※1と※2で10と100の値を2つ発行していますが、※3で取得している値は最後に発行された100の値を取得しています。以上がLatestメソッドの挙動になります。
MostRecentメソッド
Latestメソッドと同じような動きをするメソッドにMostRecentというメソッドがあります。このメソッドもIObservable
// 値の発行元 var s = new Subject<int>(); // 初期値を-1にしてIObservable<T>からIEnumerableに変換してIEnumeratorを取得 var e = s.MostRecent(-1).GetEnumerator(); // 一度も値を発行してない状態 Console.WriteLine("一度も値を発行していない場合は初期値が返される"); Console.WriteLine("MoveNext : {0}", e.MoveNext()); Console.WriteLine("CurrentValue : {0}", e.Current); Console.WriteLine("MoveNext : {0}", e.MoveNext()); Console.WriteLine("CurrentValue : {0}", e.Current); // 値を発行した状態の確認 Console.WriteLine("-----"); Console.WriteLine("OnNext(10)"); s.OnNext(10); Console.WriteLine("最後に発行した値が返されるようになる"); Console.WriteLine("MoveNext : {0}", e.MoveNext()); Console.WriteLine("CurrentValue : {0}", e.Current); Console.WriteLine("MoveNext : {0}", e.MoveNext()); Console.WriteLine("CurrentValue : {0}", e.Current); // IEnumeratorで値を取得する前に2回値が発行された状態の確認 Console.WriteLine("-----"); Console.WriteLine("OnNext(100)"); s.OnNext(100); Console.WriteLine("OnNext(1000)"); s.OnNext(1000); Console.WriteLine("最後に発行した値が返されるようになる"); Console.WriteLine("MoveNext : {0}", e.MoveNext()); Console.WriteLine("CurrentValue : {0}", e.Current); Console.WriteLine("MoveNext : {0}", e.MoveNext()); Console.WriteLine("CurrentValue : {0}", e.Current); // OnCompletedの後の状態の確認 Console.WriteLine("-----"); Console.WriteLine("OnCompleted()"); s.OnCompleted(); Console.WriteLine("OnCompletedを呼ぶと、MoveNextがFalseを返すようになる"); Console.WriteLine("MoveNext : {0}", e.MoveNext());
このコードの実行結果を下記に示します。
一度も値を発行していない場合は初期値が返される MoveNext : True CurrentValue : -1 MoveNext : True CurrentValue : -1 ----- OnNext(10) 最後に発行した値が返されるようになる MoveNext : True CurrentValue : 10 MoveNext : True CurrentValue : 10 ----- OnNext(100) OnNext(1000) 最後に発行した値が返されるようになる MoveNext : True CurrentValue : 1000 MoveNext : True CurrentValue : 1000 ----- OnCompleted() OnCompletedを呼ぶと、MoveNextがFalseを返すようになる MoveNext : False
このようにLatestではMoveNextでブロックされるようなケースでもMostRecentではブロックされずに最後の値のキャッシュを返すことが確認できます。