Zip
1. 概要
Zip は、複数の Observable ソースの値をインデックス順に組み合わせるファクトリメソッドです。各ソースの 1 番目の値同士、2 番目の値同士…のように対応する位置の値を配列にまとめて発行します。
すべてのソースが現在のインデックスの値を発行するまで待機するため、発行速度の異なるソースでも正しくペアリングされます。いずれかのソースが完了すると、結果の Observable も完了します。
2. シグネチャ
params 配列
csharp
public static Observable<T[]> Zip<T>(params Observable<T>[] sources)可変長引数で複数のソースを指定します。
csharp
Observable.Zip(sourceA, sourceB, sourceC)IEnumerable
csharp
public static Observable<T[]> Zip<T>(IEnumerable<Observable<T>> sources)ソースのコレクションを動的に渡す場合に使用します。
csharp
var sources = new List<Observable<int>> { sourceA, sourceB };
Observable.Zip(sources)オーバーロードの使い分け
| オーバーロード | 使う場面 |
|---|---|
Zip<T>(params Observable<T>[]) | ソース数がコンパイル時に決まっている場合 |
Zip<T>(IEnumerable<Observable<T>>) | ソースを動的に生成・収集する場合 |
3. マーブルダイアグラム
Zip は各ソースの値をインデックス順にペアリングします。すべてのソースが同じインデックスの値を発行するまで待機し、揃った時点で配列として発行します。いずれかのソースが完了すると結果も完了します。
4. サンプルコード
csharp
using R3;
var letters = new Subject<string>();
var numbers = new Subject<int>();
Observable.Zip(letters, numbers)
.Subscribe(values => Console.WriteLine($"[{string.Join(", ", values)}]"));
// ※ 上記は同じ型でないと使えないため、同じ型の例で示します
var subject1 = new Subject<int>();
var subject2 = new Subject<int>();
Observable.Zip(subject1, subject2)
.Subscribe(values => Console.WriteLine($"[{string.Join(", ", values)}]"));
subject1.OnNext(1); // まだ出力なし(subject2 のインデックス 0 が未到着)
subject1.OnNext(2); // まだ出力なし
subject2.OnNext(10); // 出力: [1, 10](インデックス 0 のペア)
subject2.OnNext(20); // 出力: [2, 20](インデックス 1 のペア)
subject2.OnNext(30); // まだ出力なし(subject1 のインデックス 2 が未到着)
subject1.OnNext(3); // 出力: [3, 30](インデックス 2 のペア)
subject1.OnCompleted(); // 結果も完了5. 補足
オペレーター版との違い
オペレーター版 Zip は、2〜15 個の異なる型のソースを受け取り、resultSelector 関数で結合結果を任意の型に変換できます。この静的ファクトリメソッド版は同じ型のソースのみを対象とし、結果を T[] として返します。