メインコンテンツまでスキップ

例外処理乱用の落とし穴

例外処理(try-catch)は、C#において非常に強力なエラーハンドリング手段です。しかし、その便利さゆえに「とりあえず囲っておこう」と安易に使ってしまうと、コードの品質やパフォーマンスに悪影響を及ぼすことがあります。

この記事では、例外処理の乱用による問題点再スローの誤用による問題点、正しい使い方について解説します。


✅ 例外処理の基本

C#では、例外が発生する可能性のあるコードを try ブロックで囲み、エラーが発生した場合に catch ブロックで処理します。

try
{
    int result = 10 / int.Parse("0");
}
catch (DivideByZeroException ex)
{
    Console.WriteLine("0で割ることはできません: " + ex.Message);
}

⚠️ 例外処理の乱用

❌ よくある悪い例

try
{
    if (File.Exists("data.txt"))
    {
        string content = File.ReadAllText("data.txt");
        Console.WriteLine(content);
    }
}
catch
{
    // 何もしない
}

このコードの問題点:

  • 例外を握りつぶしている(catch内が空)
  • 事前にチェックできる処理に例外を使っている
  • 何が起きたのかログも出さない

🧨 例外処理の乱用が招く問題

問題点説明
可読性の低下何が起きているのか分かりにくくなる
デバッグ困難エラーの原因が追跡できない
パフォーマンス低下例外処理はコストが高い
設計の劣化本来の制御フローが崩れる

🔁 再スローの誤用

例外をキャッチした後、適切に再スローしないことも大きな問題です。

❌ 悪い例:throw ex; を使う

catch (Exception ex)
{
    Log(ex);
    throw ex; // スタックトレースが失われる
}

この書き方では、元のスタックトレースが失われてしまい、デバッグが困難になります。


✅ 正しい再スローの方法:throw; を使う

catch (Exception ex)
{
    Log(ex);
    throw; // スタックトレースを保持したまま再スロー
}

✅ 正しい例外処理の使い方

✔️ 予測できるエラーは事前にチェック

if (File.Exists("data.txt"))
{
    string content = File.ReadAllText("data.txt");
    Console.WriteLine(content);
}
else
{
    Console.WriteLine("ファイルが存在しません。");
}

✔️ 例外は「本当に予期しない事態」に使う

try
{
    string content = File.ReadAllText("data.txt");
    Console.WriteLine(content);
}
catch (IOException ex)
{
    Console.WriteLine("ファイルの読み込み中にエラーが発生しました: " + ex.Message);
}

ベストプラクティスまとめ

  • 事前にチェックできることはチェックする
  • catchは具体的な例外型で行う
  • ログを残す
  • 例外を握りつぶさない
  • ループ内でのtry-catchは避ける

例外処理は「最後の砦」です。便利だからといって多用すると、かえってバグの温床になります。

「例外は例外的なときに使う」  この原則を忘れず、堅牢で読みやすくデバッグしやすいC#コードを目指しましょう。

参考情報