過去記事インデックス
- 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メソッド」
- Reactive Extensions再入門 その14「Nextメソッド」
- Reactive Extensions再入門 その15「To*****系メソッド」
- Reactive Extensions再入門 その16「最大、最少、平均を求めるメソッド」
- Reactive Extensions再入門 その17「集計するメソッド」
- Reactive Extensions再入門 その18「CountメソッドとLongCountメソッド」
- Reactive Extensions再入門 その19「AnyメソッドとAllメソッド」
- Reactive Extensions再入門 その20「GroupByメソッドでグルーピングしてみよう」
- Reactive Extensions再入門 その21「GroupByUntilメソッド」
- Reactive Extensions再入門 その22「単一の値を取得するメソッド」
- Reactive Extensions再入門 その23「重複を排除するメソッド」
- Reactive Extensions再入門 その24「単一の値を取得するメソッド その2」
- Reactive Extensions再入門 その25「値をまとめるBufferメソッド」
- Reactive Extensions再入門 その26「値をまとめるWindowメソッド」
- Reactive Extensions再入門 その27「時間でフィルタリング?Sampleメソッド」
- Reactive Extensions再入門 その28「落ち着いたら流すThrottleメソッド」
- Reactive Extensions再入門 その29「値を指定した時間だけ遅延させるDelayメソッド」
- Reactive Extensions再入門 その30「もう待ちきれない!を表現するTimeoutメソッド」
- Reactive Extensions再入門 その31「時間に関する情報を付与するTimestampとTimeIntervalメソッド」
- Reactive Extensions再入門 その32「型変換を行うCastとOfTypeメソッド」
- Reactive Extensions再入門 その33「シーケンスの最後を起点にSkipとTake」
- Reactive Extensions再入門 その34「ダメなら次の人!を実現するOnErrorResumeNextメソッド」
- Reactive Extensions再入門 その35「駄目ならやり直す!を実現するRetryメソッド」
- Reactive Extensions再入門 その36「ColdからHotへ!Publishメソッドと参照カウンタ?RefCountメソッド」
はじめに
前の記事でPublishの基本動作は詳しくやったので残りはさ〜っと流していきます!
引数を受け取るPublishメソッドのオーバーロード
ここでは、引数を受け取るPublishメソッドのオーバーロードについて説明します。このオーバーロードは、Subscribeしたタイミングで引数で渡した値を流します。その後、の動作は引数無しのPublishメソッドと同様にConnectメソッドを呼び出したタイミングで値を流します。このメソッドのシグネチャを以下に示します。
public static IConnectableObservable<T> Publish<T>( this IObservable<T> source, TSource initialValue);
このメソッドの使用例を下記に示します。
// Publishのintの引数を受け取るオーバーロード var source = Observable // 1〜3の値を発行するColdなObservable .Range(1, 3) // initialValueに100を指定してPublishを呼ぶ .Publish(100); // 購読 Console.WriteLine("# Subscribe"); source.Subscribe( i => Console.WriteLine("OnNext: {0}", i), () => Console.WriteLine("OnCompleted")); // 接続 Console.WriteLine("# Connect"); source.Connect();
Publishメソッドの引数に100を渡してIConnectableObservable
# Subscribe OnNext: 100 # Connect OnNext: 1 OnNext: 2 OnNext: 3 OnCompleted
Connectメソッドを呼び出す前にOnNext: 100が表示されていることが確認できます。このように、Publishメソッドの引数で渡した値がSubscribe直後に発行されていることがわかります。
PublishLastメソッド
ここでは、PublishLastメソッドについて説明します。PublishLastメソッドは最後に発行された値をConnect後に流します。このメソッドのシグネチャを以下に示します。
public static IConnectableObservable<T> PublishLast<T>(this IObservable<T> source);
このメソッドの使用例を下記に示します。
// PublishLast var source = Observable // 1〜3の値を発行するColdなObservable .Range(1, 3) // PublishLastでHot化 .PublishLast(); // 購読 Console.WriteLine("# Subscribe1"); source.Subscribe( i => Console.WriteLine("Subscribe1#OnNext: {0}", i), () => Console.WriteLine("Subscribe1#OnCompleted")); // 接続 Console.WriteLine("# Connect"); source.Connect(); // 接続後にもう一度購読 Console.WriteLine("# Subscribe2"); source.Subscribe( i => Console.WriteLine("Subscribe2#OnNext: {0}", i), () => Console.WriteLine("Subscribe2#OnCompleted"));
Connect前に1回購読(Subscribe1)をして、Connect後にもう一度購読(Subscribe2)しています。このコードの実行結果を以下に示します。
# Subscribe1 # Connect Subscribe1#OnNext: 3 Subscribe1#OnCompleted # Subscribe2 Subscribe2#OnNext: 3 Subscribe2#OnCompleted
OnNextに、元になるIObservable
Multicastメソッド
ここでは、Multicastメソッドについて説明します。Multicastメソッドは引数に応じて、Publishメソッド、引数のあるPublishメソッド、PublishLastメソッドと同じ動きをするIConnectableObservable
public static IConnectableObservable<T> Multicast<T, U>( this IObservable<T> source, ISubject<T, U> subject);
引数のsubjectに応じてPublish系の各メソッドと同じ動作をさせることが出来ます。ISubject
public static IConnectableObservable<T> Multicast<T >( this IObservable<T> source, ISubject<T > subject);
このメソッドの使用例を下記に示します。
Console.WriteLine("# Multicast(new Subject<int>())"); var source = Observable .Range(1, 3) // Publishと一緒 .Multicast(new Subject<int>()); // 購読 Console.WriteLine("# Subscribe"); source.Subscribe( i => Console.WriteLine("OnNext: {0}", i), () => Console.WriteLine("OnCompleted")); // 接続 Console.WriteLine("# Connect"); source.Connect();
上記コードではMulticastメソッドにSubject
# Multicast(new Subject<int>()) # Subscribe # Connect OnNext: 1 OnNext: 2 OnNext: 3 OnCompleted
Publishメソッドと同様にConnect後に、値が発行されていることが確認できます。
次に、BehaviorSubject
Console.WriteLine("# Multicast(new BehaviorSubject<int>(100))"); var source = Observable .Range(1, 3) // Publish(100)と一緒 .Multicast(new BehaviorSubject<int>(100)); // 購読 Console.WriteLine("# Subscribe"); source.Subscribe( i => Console.WriteLine("OnNext: {0}", i), () => Console.WriteLine("OnCompleted")); // 接続 Console.WriteLine("# Connect"); source.Connect();
BehaviorSubject
# Multicast(new BehaviorSubject<int>(100)) # Subscribe OnNext: 100 # Connect OnNext: 1 OnNext: 2 OnNext: 3 OnCompleted
引数のあるPublishメソッドと同様にSubscribe直後に値が発行されて、Connect後に元になるIObservable
次に、AsyncSubject
Console.WriteLine("# Multicast(new AsyncSubject<int>())"); var source = Observable .Range(1, 3) // PublishLastと一緒 .Multicast(new AsyncSubject<int>()); // 購読 Console.WriteLine("# Subscribe"); source.Subscribe( i => Console.WriteLine("OnNext: {0}", i), () => Console.WriteLine("OnCompleted")); // 接続 Console.WriteLine("# Connect"); source.Connect();
AsyncSubject
# Multicast(new AsyncSubject<int>()) # Subscribe # Connect OnNext: 3 OnCompleted
上記の実行結果からもわかるとおり、最後の値だけが発行されています。このことから、AsyncSubject
このMulticastメソッドは、任意のSubjectを渡すことによってColdなIObservable