Select
1. 概要
Select は、上流から流れてくる各値に変換関数を適用し、その結果を下流へ流すオペレーターです。
LINQ の Select や他言語の map に相当します。上流の要素数、タイミング、完了通知、エラー通知はそのまま下流へ伝搬し、値だけが変換されます。
R3 の実装では、上流が Where である場合に内部的に WhereSelect へ最適化されるため、Where(...).Select(...) のチェーンはオーバーヘッドが最小になります。
2. シグネチャ
値を変換する
csharp
public static Observable<TResult> Select<T, TResult>(this Observable<T> source, Func<T, TResult> selector)最も基本的な overload です。各値に selector を適用し、変換結果を下流へ流します。
csharp
source.Select(x => x * 2)インデックス付きで変換する
csharp
public static Observable<TResult> Select<T, TResult>(this Observable<T> source, Func<T, int, TResult> selector)selector の第2引数に 0 始まりのインデックスが渡されます。何番目の値かを利用した変換に使います。
csharp
source.Select((x, i) => $"{i}: {x}")外部状態を使って変換する
csharp
public static Observable<TResult> Select<T, TResult, TState>(this Observable<T> source, TState state, Func<T, TState, TResult> selector)クロージャによるキャプチャを避けたい場合に、外部状態を引数として明示的に渡せます。パフォーマンスが重要な場面で有用です。
csharp
var factor = 10;
source.Select(factor, (x, f) => x * f)外部状態とインデックス付きで変換する
csharp
public static Observable<TResult> Select<T, TResult, TState>(this Observable<T> source, TState state, Func<T, int, TState, TResult> selector)インデックスと外部状態の両方を利用できる overload です。
csharp
source.Select(offset, (x, i, o) => x + i + o)overload の使い分け
| overload | 使う場面 |
|---|---|
Select(Func<T, TResult>) | 通常の値変換 |
Select(Func<T, int, TResult>) | インデックスを利用した変換 |
Select(TState, Func<T, TState, TResult>) | クロージャ回避でパフォーマンス向上 |
Select(TState, Func<T, int, TState, TResult>) | インデックスとクロージャ回避の両方が必要な場合 |
3. マーブルダイアグラム
この例では、上流から 1、2、3 が流れ、Select(x => x * 10) によって 10、20、30 として下流へ流れます。
4. サンプルコード
csharp
using R3;
var source = Observable.Range(1, 5);
source.Select(x => x * x)
.Subscribe(x => Console.WriteLine(x));
// 出力: 1, 4, 9, 16, 25インデックス付きの例:
csharp
using R3;
var source = Observable.Range(10, 3);
source.Select((x, i) => $"[{i}] = {x}")
.Subscribe(x => Console.WriteLine(x));
// 出力: [0] = 10, [1] = 11, [2] = 12