Skip to content

Where

1. 概要

Where は、ソースシーケンスの各要素に対して条件(predicate)を評価し、条件を満たす要素のみを通過させるフィルタリングオペレーターです。LINQ の Where と同様の動作で、リアクティブシーケンスにおける最も基本的なフィルタリング手段です。

2. シグネチャ

条件関数によるフィルタリング

csharp
public static Observable<T> Where<T>(
    this Observable<T> source,
    Func<T, Boolean> predicate)

条件関数 predicatetrue を返す要素のみを下流に流します。

csharp
// 偶数のみ通過させる
source.Where(x => x % 2 == 0);

インデックス付き条件関数によるフィルタリング

csharp
public static Observable<T> Where<T>(
    this Observable<T> source,
    Func<T, int, Boolean> predicate)

条件関数の第 2 引数に 0 始まりのインデックスが渡されます。要素の位置に基づくフィルタリングが可能です。

csharp
// 3 番目以降(index >= 2)かつ正の値のみ通過させる
source.Where((x, index) => index >= 2 && x > 0);

overload の使い分け

overload使う場面
Func<T, Boolean>要素の値だけで判定できる場合(一般的)
Func<T, int, Boolean>要素の出現順序(インデックス)も判定に必要な場合

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

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

ソースシーケンスの各要素に対して条件を評価し、条件を満たす要素(図中の色付き要素)のみが下流に流れます。条件を満たさない要素は破棄されます。

4. サンプルコード

csharp
using R3;

// 基本的なフィルタリング:偶数のみ取得
var source = Observable.Range(1, 10);

source
    .Where(x => x % 2 == 0)
    .Subscribe(x => Console.WriteLine($"偶数: {x}"));
// 出力:
// 偶数: 2
// 偶数: 4
// 偶数: 6
// 偶数: 8
// 偶数: 10

// インデックス付きフィルタリング:最初の 3 要素をスキップしつつ条件を適用
var values = new[] { 10, -5, 3, 7, -2, 8 };
values.ToObservable()
    .Where((x, index) => index >= 3 && x > 0)
    .Subscribe(x => Console.WriteLine($"値: {x}"));
// 出力:
// 値: 7
// 値: 8

5. 補足

WhereAwait との違い

条件判定に非同期処理(HTTP リクエストやデータベースクエリなど)が必要な場合は WhereAwait を使用してください。Where は同期的な条件関数のみをサポートします。

WhereSelect 最適化

R3 の内部実装では、Where の直後に Select をチェーンした場合、WhereSelect という最適化されたオペレーターに自動的に結合されます。これにより、2 つのオペレーターを個別に実行するよりもオーバーヘッドが削減されます。

csharp
// 内部的に WhereSelect に最適化される
source
    .Where(x => x > 0)
    .Select(x => x * 2);

この最適化はユーザーが意識する必要はなく、自動的に適用されます。