Skip to content

MaxAsync

1. 概要

MaxAsync は、Observable シーケンス内の最大値を求め、その結果を Task<T> として返すオペレーターです。シーケンスが完了するまですべての要素を評価します。シーケンスが空の場合は InvalidOperationException をスローします。

2. シグネチャ

デフォルト比較による最大値

csharp
public static Task<T> MaxAsync<T>(
    this Observable<T> source,
    CancellationToken cancellationToken = default)
    where T : IComparable<T>

型パラメーター TIComparable<T> を実装している場合に使用できます。

セレクターによる射影後の最大値

csharp
public static Task<TResult> MaxAsync<T, TResult>(
    this Observable<T> source,
    Func<T, TResult> selector,
    CancellationToken cancellationToken = default)
    where TResult : IComparable<TResult>

各要素を selector で変換した結果から最大値を求めます。

カスタム比較子による最大値

csharp
public static Task<T> MaxAsync<T>(
    this Observable<T> source,
    IComparer<T> comparer,
    CancellationToken cancellationToken = default)

IComparer<T> を指定して、独自の比較ロジックで最大値を判定します。

セレクター + カスタム比較子による最大値

csharp
public static Task<TResult> MaxAsync<T, TResult>(
    this Observable<T> source,
    Func<T, TResult> selector,
    IComparer<TResult> comparer,
    CancellationToken cancellationToken = default)

各要素を selector で変換した結果を、指定した IComparer<TResult> で比較して最大値を求めます。

オーバーロードの使い分け

オーバーロード用途
MaxAsync(source)要素自体が IComparable<T> を実装している場合
MaxAsync(source, selector)要素の特定のプロパティから最大値を求めたい場合
MaxAsync(source, comparer)カスタム比較ロジックを使いたい場合
MaxAsync(source, selector, comparer)変換後の値にカスタム比較ロジックを使いたい場合

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

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

シーケンスのすべての要素を収集し、完了時に最大値を単一の結果として出力します。

4. サンプルコード

csharp
// 基本的な使い方:数値シーケンスの最大値
var source = Observable.Create<int>(observer =>
{
    observer.OnNext(3);
    observer.OnNext(7);
    observer.OnNext(2);
    observer.OnNext(9);
    observer.OnNext(5);
    observer.OnCompleted();
    return Disposable.Empty;
});

int max = await source.MaxAsync();
Console.WriteLine(max); // 9
csharp
// セレクターを使ってオブジェクトのプロパティから最大値を取得
var students = new[]
{
    new { Name = "田中", Score = 85 },
    new { Name = "鈴木", Score = 92 },
    new { Name = "佐藤", Score = 78 },
};

int maxScore = await students.ToObservable().MaxAsync(s => s.Score);
Console.WriteLine(maxScore); // 92
csharp
// カスタム比較子を使用
var comparer = Comparer<string>.Create((a, b) => a.Length.CompareTo(b.Length));
string longest = await Observable.Return(new[] { "apple", "hi", "watermelon" })
    .SelectMany(x => x.ToObservable())
    .MaxAsync(comparer);
Console.WriteLine(longest); // watermelon
csharp
// セレクターとカスタム比較子を併用
var words = new[] { "apple", "HI", "Watermelon" }.ToObservable();
var comparer = StringComparer.OrdinalIgnoreCase;

string maxWord = await words.MaxAsync(x => x, comparer);
Console.WriteLine(maxWord); // Watermelon

5. 補足

  • MinAsync は最小値を返す逆の操作です。
  • MinMaxAsync を使うと、最小値と最大値を 1 回のパスで同時に取得できます。最大値と最小値の両方が必要な場合は MinMaxAsync の方が効率的です。