C#中級

中級 C#で学ぶ例外設計|アンチパターン編

導入

例外処理は、プログラムの安定性と信頼性を高めるために不可欠な要素です。しかし、誤った設計や実装は、逆に問題を引き起こすことがあります。本記事では、C#を用いた例外設計における一般的なアンチパターンを紹介し、それらがなぜ問題なのか、どのように改善できるのかを具体的なコード例を通じて解説します。

教科書レベルの解説(例外設計)

重要な概念の整理

例外設計では、エラーが発生した際にどのように処理するかが重要です。エラーハンドリングの方法には、try-catchブロックを用いる方法や、特定の例外を投げる方法があります。これらの手法を適切に利用することで、プログラムの可読性や保守性を向上させることができます。しかし、設計が不十分だと、エラーが隠れてしまったり、デバッグが難しくなったりすることがあります。

コード例(C#)


// ファイルの読み込みを行うメソッド
public string ReadFile(string filePath)
{
    try
    {
        return System.IO.File.ReadAllText(filePath);
    }
    catch (Exception ex)
    {
        // 例外を単にログに記録するだけの実装
        Console.WriteLine($"Error reading file: {ex.Message}");
        return string.Empty;
    }
}

コードの行ごとの解説

  1. tryブロック内でファイルを読み込む処理が行われている。
  2. catchブロックで例外を捕捉し、エラーメッセージをコンソールに出力している。
  3. エラーが発生した場合、空の文字列を返すことで呼び出し元にエラーを伝えている。

アンチパターン編

上記のコードは、例外処理の一般的なアンチパターンの一例です。特に、例外が発生した場合に単にエラーメッセージをログに記録し、空の文字列を返すだけでは、問題の本質を隠してしまいます。呼び出し元は、ファイルが正常に読み込まれたかどうかを判断する手段を持たず、エラーの原因を追跡することが難しくなります。

この問題を解決するためには、例外を適切に再スローすることが重要です。具体的には、次のように改善できます。


// 改善されたファイル読み込みメソッド
public string ReadFile(string filePath)
{
    try
    {
        return System.IO.File.ReadAllText(filePath);
    }
    catch (Exception ex)
    {
        // 例外を再スローし、呼び出し元で処理させる
        throw new IOException($"Failed to read file at {filePath}", ex);
    }
}

この改善により、例外が発生した際に、呼び出し元はファイルパスとともに詳細なエラーメッセージを受け取ることができ、適切なエラーハンドリングが可能になります。

まとめ

  • 例外処理は、プログラムの安定性を保つために重要な要素である。
  • 単にエラーメッセージをログに記録するだけでは、問題の本質を隠すことになる。
  • 例外を再スローすることで、呼び出し元に詳細な情報を提供し、適切なエラーハンドリングを促すことができる。