LINQでやらかしやすいポイントまとめ【C#】

C#

はじめに

ここまで、LINQの基本的な使い方や、
個人開発の中でよく使っているメソッドをまとめてきました。

LINQはとても便利ですが、
使い方を間違えると「思っていた動きと違う」ということもあります。

今回は、個人開発の中で
「ここは気をつけた方がいい」と感じたポイントをまとめてみます。

① First と FirstOrDefault の違い

まず注意したいのが、First()FirstOrDefault() の違いです。

var item = items.First(x => x.Id == targetId);

First() は、条件に合うデータが1件もなかった場合、
例外(エラー)になります。

一方で、FirstOrDefault() は、

var item = items.FirstOrDefault(x => x.Id == targetId);

該当データがなければ null を返します。

そのため、個人開発では
基本的に FirstOrDefault() を使い、
nullチェックを入れるようにしています。

if (item != null)
{
    // 処理
}

「必ず存在する」と分かっている場合以外は、
FirstOrDefault() の方が安全だと感じています。

② nullの扱いを忘れがち

LINQは便利ですが、
戻り値が null になる可能性を忘れがちです。

例えば、

  • FirstOrDefault()
  • SingleOrDefault()

などは、該当データがなければ null になります。

nullチェックを忘れると、
後続処理で NullReferenceException が発生します。

LINQを書いた後は、

「これ、nullになる可能性あるかな?」

と一度考えるようにしています。

③ ToListを付けすぎる問題

前回の記事でも触れましたが、
ToList() は便利です。

ただ、なんとなく毎回付けてしまうと、
不要なメモリ確保や無駄な処理が発生することもあります。

例えば、

var total = items
    .Where(x => x.IsChecked)
    .ToList()
    .Sum(x => x.Amount);

この場合、ToList() を挟まなくても動きます。

var total = items
    .Where(x => x.IsChecked)
    .Sum(x => x.Amount);

「今この状態を固定したいのか?」
を意識して、必要なときだけ ToList() を使うようにしています。

④ チェーンしすぎて読みにくくなる

LINQはつなげて書けるのが魅力ですが、
長くなりすぎると逆に読みにくくなります。

var result = items
    .Where(x => x.IsChecked)
    .Select(x => new { x.Name, x.Amount })
    .Where(x => x.Amount > 0)
    .OrderBy(x => x.Name)
    .ToList();

処理としては正しいですが、
条件や変換が増えると、
「何をしているのか」を一度で理解しにくくなります。

そのような場合は、

  • 途中で変数に分ける
  • 処理をメソッドに切り出す

などの工夫をした方が、読みやすくなることもあります。

⑤ LINQにこだわりすぎない

最後に感じているのは、

「全部LINQで書かなくていい」

ということです。

複雑な分岐や処理が絡む場合は、
素直に foreach で書いた方が分かりやすいこともあります。

LINQはあくまで選択肢のひとつ。

  • 単純な絞り込み
  • 単純な変換
  • 単純な集計

こういった場面で使うのが、今の自分にはちょうど良いと感じています。

まとめ

LINQはとても便利ですが、

  • First と FirstOrDefault の違い
  • nullの可能性
  • ToListの使いどころ
  • 書きすぎによる可読性低下

このあたりは意識しておくと、
トラブルを減らせると感じました。

便利だからこそ、
「なぜこの書き方にしているのか」を
自分なりに説明できる状態にしておくことが大事だと思っています。

個人開発を通して、
少しずつ理解を深めていければと考えています。