Race
1. 概要
Race は、複数の Observable のうち最初に値を発行したものを「勝者」とし、それ以外のすべての Observable の購読を解除するオペレーターです。
勝者が決定した後は、勝者の Observable からの要素のみが下流へ流れます。従来の Rx では Amb と呼ばれていたオペレーターが、R3 では Race にリネームされています。
2. シグネチャ
2 つの Observable で競争する(オペレーターオーバーロード)
csharp
public static Observable<T> Race<T>(this Observable<T> source, Observable<T> second)2 つの Observable のうち、先に値を発行した方を採用します。
csharp
source.Race(second)可変個数の Observable で競争する(ファクトリメソッド)
csharp
public static Observable<T> Race<T>(params Observable<T>[] sources)
public static Observable<T> Race<T>(IEnumerable<Observable<T>> sources)任意の個数の Observable のうち、最初に値を発行したものを採用します。
csharp
Observable.Race(source1, source2, source3)overload の使い分け
| overload | 使う場面 |
|---|---|
Race(Observable<T>) | 2 つの Observable を競争させる基本的なケース |
Race(params Observable<T>[]) | 3 つ以上の Observable を競争させる場合 |
Race(IEnumerable<Observable<T>>) | コレクションとして渡す場合 |
3. マーブルダイアグラム
最初に値を発行した Observable が勝者となり、他の Observable は購読解除されます。以降は勝者の要素のみが下流へ流れます。
4. サンプルコード
csharp
using R3;
var fast = new Subject<string>();
var slow = new Subject<string>();
fast.Race(slow)
.Subscribe(x => Console.WriteLine(x));
slow.OnNext("遅い"); // slow が先に発行 → slow が勝者
fast.OnNext("速い"); // 出力なし(fast は購読解除済み)
slow.OnNext("継続"); // 出力: 継続複数ソースでの競争:
csharp
using R3;
// 複数のサーバーにリクエストを送り、最初に応答したものを採用
var server1 = FetchFromServer("https://server1.example.com/api");
var server2 = FetchFromServer("https://server2.example.com/api");
var server3 = FetchFromServer("https://server3.example.com/api");
Observable.Race(server1, server2, server3)
.Subscribe(response => ProcessResponse(response));5. 補足
Merge との違い
Merge はすべてのソースに同時に購読し、届いた値をすべて下流に流します。Race は最初に値を発行したソースのみを採用し、他は即座に購読解除します。
| 特性 | Race | Merge |
|---|---|---|
| 採用するソース | 最初に発行した 1 つだけ | すべて |
| 敗者の扱い | 購読解除 | 継続して購読 |
| 典型的な用途 | 冗長系からの最速応答 | 複数イベントの集約 |
旧名称 Amb について
R3 では、従来の Reactive Extensions で Amb(ambiguous の略)と呼ばれていたオペレーターが Race にリネームされています。Amb は互換性のために残されていますが、[Obsolete] 属性が付与されているため、新しいコードでは Race を使用してください。
ファクトリメソッド版との違い
ファクトリメソッド版 Race は、Observable.Race(source1, source2, source3) のように複数ソースをまとめて指定する場合に使います。2 つのソースだけを競争させる場合は、このオペレーター版の source.Race(second) が読みやすくなります。