LoginSignup
14
15

More than 5 years have passed since last update.

C# LINQ Aggregate のオーバーロードの挙動を知る

Posted at

そもそもAggregateとはなんぞや

ある集合(IEnumerable<TSource>)に対して処理を通して1つの結果(TSource または TAccumulate)を受け取る集合系メソッドです。
要するに T[] があった時に T 一つひとつに何らかの処理を通して集計した結果を返す的なイメージでOK。
Haskellでいうfoldみたいな。

で、これを使う時3つほどオーバーロードがあるんですが、それぞれの挙動がちょっとだけ気になったので調べてみた。

オーバーロードについて

public static TSource Aggregate<TSource>(
        this IEnumerable<TSource> source,
        Func<TSource, TSource, TSource> func) { return /* hogemoge */ }

public static TAccumulate Aggregate<TSource, TAccumulate>(
        this IEnumerable<TSource> source,
        TAccumulate seed,
        Func<TAccumulate, TSource, TAccumulate> func) { return /* hogemoge */ }

public static TResult Aggregate<TSource, TAccumulate, TResult>(
        this IEnumerable<TSource> source,
        TAccumulate seed,
        Func<TAccumulate, TSource, TAccumulate> func,
        Func<TAccumulate, TResult> resultSelector) { return /* hogemoge */ }

と、3種類あります。
内容は見てわかるので割愛。気が向いた時に中身の解説するかもめ。

で、今回注目したいのは、Seedを渡す時と渡さない時の動作の違い。
ちょっと考えれば当たり前なんだけど忘れがちなので。

まずSeedを与えない場合。

// 要素ゼロでもLINQなら。そんなふうに考えていた時期が俺にもありました。
Enumerable.Empty<int>().Select(i => i.ToString())
          .Aggregate((acc, succ) => acc + succ); //=> InvalidOperationException

// string.Join みたいなことする
Enumerable.Range(1, 10).Select(i => i.ToString())
      .Aggregate((acc, succ) => acc + "," + succ); //=> "1,2,3,4,5,6,7,8,9,10"

次にSeedを与える場合。

// エラー出さない
Enumerable.Empty<int>().Select(i => i.ToString())
      .Aggregate("", (acc, succ) => acc + "," + succ); //=> ""

// string.Join みたいなことしたい人生だった
Enumerable.Range(1, 10).Select(i => i.ToString())
      .Aggregate("", (acc, succ) => acc + "," + succ); //=> ",1,2,3,4,5,6,7,8,9,10"

はい、エラーが出なくなりますし頭に "," がつきます。

何が違うのか

seedを与えない場合、IEnumerableから取得できる1つ目の要素がseedとして使用されるため、
1つ目の要素が存在しない場合にエラーになります。

次にseedを与えた場合、それがseedとして使用されるため、最初の1ループ目に空文字と1つ目の要素がつながって
カンマが付与されるので先頭にカンマがつきます。

すごく単純だけど忘れがちなのでご注意ください。


おまけ。C#のSyntax Highlightがカラーパターンガン無視であまりにもひどくていらいらなどした。

こうでしょ!こう!

color1.png
color2.png

14
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
15