【C#】例外発生時に詳細情報を取得する方法:Message, StackTrace, TargetSiteの活用

アプリケーションの運用中、予期せぬエラーが発生した場合、単に「エラーが発生しました」と表示するだけでは原因の特定が困難です。C#の例外オブジェクト(Exceptionクラスおよびその派生クラス)には、エラーの原因究明に役立つ詳細な情報がプロパティとして格納されています。

ここでは、KPI(重要業績評価指標)の計算処理中にゼロ除算エラーが発生したケースを想定し、例外オブジェクトから「エラー内容」「発生箇所」「メソッド名」などの情報を取得してログに出力する方法を解説します。


目次

例外オブジェクトの主要プロパティ

catchブロックで捕捉した例外変数(通常はexeと命名)を通じて、以下のプロパティにアクセスすることで詳細情報を取得できます。

  1. Message: エラーの概要説明(「0 で除算しようとしました。」など)。
  2. StackTrace: エラー発生時のメソッド呼び出し履歴(スタックトレース)。どの行でエラーが起きたかを特定するために最も重要です。
  3. Source: 例外を発生させたアプリケーションまたはオブジェクトの名前。
  4. TargetSite: 例外をスローしたメソッドの情報(リフレクション情報)。

実践的なコード例:売上分析システムでのエラー解析

以下のコードは、店舗の「客単価(売上 ÷ 来店客数)」を計算するプログラムです。データ不備により来店客数が「0」になった場合に発生するDivideByZeroExceptionを捕捉し、詳細情報をコンソールに出力します。

using System;

namespace StoreAnalysis
{
    class Program
    {
        static void Main()
        {
            // シナリオ:
            // 店舗のPOSデータから客単価を計算するバッチ処理。
            // データ不整合により、来店客数が 0 のデータが混入してしまった。

            int dailySales = 150000; // 売上金額
            int visitorCount = 0;    // 来店客数(エラーの原因)

            try
            {
                // 客単価の計算処理を呼び出し
                int avgSpend = CalculateAverageSpend(dailySales, visitorCount);
                Console.WriteLine($"客単価: {avgSpend:C}");
            }
            catch (DivideByZeroException ex)
            {
                // 例外オブジェクト(ex)から詳細情報を取得して出力
                Console.WriteLine("=== エラーレポート ===");
                
                // 1. エラーメッセージ(何が起きたか)
                Console.WriteLine($"[Message]    : {ex.Message}");
                
                // 2. 発生元アプリケーション名
                Console.WriteLine($"[Source]     : {ex.Source}");
                
                // 3. 例外が発生したメソッド名
                // ※TargetSiteはnullになる場合もあるため、nullチェックを行うのが安全です
                if (ex.TargetSite != null)
                {
                    Console.WriteLine($"[TargetSite] : {ex.TargetSite}");
                }

                // 4. スタックトレース(どこで起きたか)
                Console.WriteLine($"[StackTrace] :\n{ex.StackTrace}");
            }
            catch (Exception ex)
            {
                // その他の予期せぬエラー
                Console.WriteLine($"[Critical Error] {ex.Message}");
            }
        }

        // 客単価を計算するメソッド
        static int CalculateAverageSpend(int sales, int visitors)
        {
            // 整数同士の割り算で分母が0の場合、ここで DivideByZeroException が発生する
            return sales / visitors;
        }
    }
}

実行結果

=== エラーレポート ===
[Message]    : 0 で除算しようとしました。
[Source]     : StoreAnalysis
[TargetSite] : Int32 CalculateAverageSpend(Int32, Int32)
[StackTrace] :
   at StoreAnalysis.Program.CalculateAverageSpend(Int32 sales, Int32 visitors) in C:\Work\StoreAnalysis\Program.cs:line 53
   at StoreAnalysis.Program.Main() in C:\Work\StoreAnalysis\Program.cs:line 19

技術的なポイントと注意点

1. StackTraceの重要性

デバッグにおいて最も有益なのがStackTraceです。上記の実行結果のように、「どのファイルの」「何行目で」「どのメソッドが呼ばれたか」が記録されています。ログファイルにエラーを出力する際は、Messageだけでなく必ずStackTraceも含めるように実装することで、トラブルシューティングの速度が劇的に向上します。

2. ToString()メソッドの活用

個別のプロパティにアクセスせずとも、ex.ToString()メソッドを呼び出すことで、例外の型、Message、StackTraceを含む整形された文字列を一括で取得できます。簡易的なログ出力であればToString()で十分な場合が多いですが、ログのフォーマットを細かく制御したい場合(JSON形式で保存したい場合など)は、上記のように個別のプロパティへアクセスします。

3. TargetSiteの制約

TargetSiteプロパティは、例外をスローしたメソッドのMethodBaseオブジェクトを返します。ただし、.NETの実行環境(特にAOTコンパイル環境や特定の最適化が施された環境)によっては、この情報が正しく取得できずnullになる場合があります。利用する際は必ずnullチェックを行うか、厳密なメソッド特定が必要な場合はStackTraceの解析を優先してください。

まとめ

例外オブジェクトは、エラー解決の手がかりとなる情報の宝庫です。単にエラーメッセージを表示するだけでなく、StackTraceSourceなどの情報を適切に記録することで、本番環境での障害発生時にも迅速な原因特定が可能になります。堅牢なシステム運用のために、例外情報の活用は必須のテクニックです。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次