Skip to content

Concat

1. 概要

Concat は、複数の Observable シーケンスを直列に連結するオペレーターです。最初の Observable が完了した後に次の Observable を購読し、すべてのソースを順番に処理します。

各ソースの要素は発行順を保ったまま下流へ流れ、すべてのソースが完了したときに結果のシーケンスも完了します。

2. シグネチャ

2 つの Observable を連結する(オペレーターオーバーロード)

csharp
public static Observable<T> Concat<T>(this Observable<T> source, Observable<T> second)

source が完了した後に second を購読します。

csharp
source.Concat(second)

可変個数の Observable を連結する(ファクトリメソッド)

csharp
public static Observable<T> Concat<T>(params Observable<T>[] sources)
public static Observable<T> Concat<T>(IEnumerable<Observable<T>> sources)

配列や IEnumerable で渡された複数の Observable を、先頭から順に購読して連結します。

csharp
Observable.Concat(source1, source2, source3)

Observable の Observable をフラット化する

csharp
public static Observable<T> Concat<T>(this Observable<Observable<T>> sources)

外側の Observable が内側の Observable を発行するたびに、前の内側 Observable が完了してから次を購読します。

csharp
outerObservable.Concat()

overload の使い分け

overload使う場面
Concat(Observable<T>)2 つの Observable を直列に連結する基本的なケース
Concat(params Observable<T>[])3 つ以上の Observable を順番に連結する場合
Concat(IEnumerable<Observable<T>>)コレクションとして渡す場合
Concat(Observable<Observable<T>>)ネストされた Observable を直列にフラット化する場合

3. マーブルダイアグラム

Concat のマーブルダイアグラム

最初のソースが完了した後に、次のソースの要素が続けて下流へ流れます。

4. サンプルコード

csharp
using R3;

var first = Observable.Create<string>(observer =>
{
    observer.OnNext("A");
    observer.OnNext("B");
    observer.OnCompleted();
    return Disposable.Empty;
});

var second = Observable.Create<string>(observer =>
{
    observer.OnNext("C");
    observer.OnNext("D");
    observer.OnCompleted();
    return Disposable.Empty;
});

first.Concat(second)
    .Subscribe(x => Console.WriteLine(x));
// 出力:
// A
// B
// C
// D

ファクトリメソッド版 Concat の例:

csharp
using R3;

var sources = new[]
{
    Observable.Return(1),
    Observable.Return(2),
    Observable.Return(3)
};

Observable.Concat(sources)
    .Subscribe(x => Console.WriteLine(x));
// 出力: 1, 2, 3

5. 補足

Merge との違い

Merge はすべてのソースに同時に購読するため、要素がソース単位ではなく到着順に流れます。Concat は前のソースが完了するまで次のソースを購読しないため、要素の順序がソース単位で保証されます。

Switch との違い

Switch は最新の内部 Observable のみを購読し、以前の購読を破棄します。Concat はすべての内部 Observable を順番に購読し、1 つも見逃しません。

ファクトリメソッド版との違い

ファクトリメソッド版 Concat は、Observable.Concat(source1, source2, source3) のように複数ソースをまとめて指定する場合に使います。2 つのソースを直列につなぐだけなら、このオペレーター版の source.Concat(second) が読みやすくなります。