【C#】Listで要素を絞り込むFindAllとWhereは何が違うのか

List型で絞り込むときFindAllとWhereが使えます。
FindAllとWhereは書き方も似ていて、
どっちを使ったらいいかわからない方向けにこの記事をかきます。

結論は「大量のデータを扱うとき、Whereを利用するとよい」になるのですけれども、
そこに至るまでのWhereの特徴を合わせて紹介します。

それでは本文です。

書き方はFindAllのほうがシンプル

まずはこちらをご覧ください。


よくある「本」 クラスですね。

List<Book>を用意してPriceが10$以下の本を絞り込むFindAllとWhereそれぞれ記載してみましょう。


似てます。書き方もほぼ一緒です。
違いがあるとするとWhereを利用した場合に、ToListが必要なことでしょうか。

あとあと、このToListが効いてくるのですけれども、単純な比較ではToListが無く、
シンプルに記載できるFindAllを使いたくなりますね。

WhereでパフォーマンスがでるのはToListが肝

書き方も似ていますし、一回の絞り込みではまたパフォーマンスもほとんど変わりません。
対して、差が出るのは次のような場合です。
1$以上、10$以下、IDに「bk」が含まれる本の絞り込みです。

まずはFindAll


続いてWhere


ポイントになるのは、先程邪険に扱った「ToList()」
このToListこそがWhereのメリットを享受するための仕組なのです。

Whereの特徴は一度に計算

FindAllとWhereの違いは上述です。
FindAllが毎回Listを生成するのに対して、
WhereはToListを使用した時にListを生成します。

それまでのfirst,secondで記載しているWhereは条件をため込んで
その場ではListを生成しません。
そしてToListで一度に計算することで効率化をおこないます。

この特徴を「遅延評価」と呼んだりします。

この効率化こそが、大量のデータを扱う上でパフォーマンスメリットを生み出します。

私の手元では7万のBookデータの絞り込みで1.5~2倍程度の差が出ました。
扱うデータ数が大きければ大きいほど、また、扱う条件が多ければ多いほどWhereの威力を発揮するでしょう。

Whereが活躍する場面例

「いやいや、金額で絞り込み書けるだけならば、FindAllでも一発で書けるじゃないか」と思われる方もいらっしゃると思います。

実際に書くとこんな感じ。


これならFindAllを使用しても一発で絞り込みができますし、シンプルです。

ただし、この書き方は「本」を検索するときに毎回必ず最低金額、最高金額の絞り込みがあった場合に有効です。

実際世に出ているサービスを例にとると、本を購入するサイトなどは
最低金額、最高金額を入力するかどうかはユーザーの入力次第になります。

最低金額があるなら最低金額の絞り込みをしたいし、無いなら絞り込みをしない。
つまりは、条件が動的に変わる場合こそWhereの出番です。


Whereを用いるならば最後にListを生成するまでは、複数の条件を付けたり付けなかったりできます。

FindAllで同じことをしようとすると、List が複数生成される、
メソッドのネストが深くなったり三項演算子で可読性が落ちるなどのデメリットが生じる
可能性があります。

まとめ

さくっとまとめると、

  • 一回の絞り込みであれば、FindAllのほうがシンプルに記述できる
  • 大量のデータを扱う場合はWhereのほうが有利
  • 動的にしぼり込みを変えるときもWhereのほうが有利

です。

FindAllを使用するかWhereを使用するのか迷われている方の参考になれば幸いです。

では。