web-dev-qa-db-ja.com

C#で情報を失うことなく、例外にメッセージを追加するにはどうすればよいですか?

私は次のコードを持っています:

catch(Exception ex)
{
    throw new FatalException("An error occurred while trying to load the XSLT file.", ex);
}

残念ながら、これは例外を飲み込みます。これを修正するには、次を実行します。

catch(Exception ex)
{
    throw;
}

ただし、イベントログのヘルプのためにカスタムメッセージを含めたいと思います。

情報を失わずにこのメッセージを例外に追加するにはどうすればよいですか? (スタックトレース/デバッグシンボルなど)

54
Codeman

ユーザーが読み取り可能なメッセージや、エラーの追跡には役立つがエンドユーザーには役に立たない特定の詳細などの情報を元の例外に追加するだけでよい場合は、例外の Data プロパティ。キー/値ペアの辞書です。

実行中のレポートや処理中のファイルなどの情報を記録するためにこれを広範に使用し、エラー時に正確に何が起こっていたかをオペレーションが判断できるようにします。ユーザーは障害の原因に直接取り組んでいるので、この詳細は必要ありません。

これを使用して、ユーザーにとって意味のあるプレーンテキストメッセージを渡すこともできます。唯一の問題は、データを抽出し、消費者に役立つようにするために、ロギングフレームワークまたはエンドユーザーインターフェイスで追加の作業を実行する必要があることです。

たとえば、次のことができます。

catch (Exception ex)
{
    ex.Data.Add("UserMessage", "An error occurred while trying to load the XSLT file.");
    throw;
}

次に、クライアント側のコードで、UserMessageが存在するかどうかをテストし、存在する場合は、例外ではなくユーザーに提示します。

catch (Exception ex)
{
    if (ex.Data.Contains("UserMessage"))
    {
        MessageBox.Show(ex.Data["UserMessage"].ToString());
    }
    else
    {
        MessageBox.Show(ex.Message);
    }
}
68
competent_tech

その元の例外はまだそこにあります。

例外ロギングを行う場合、受け取る例外は、メッセージで作成したFatalExceptionになります。元の例外はex.InnerExceptionにあります。スタックトレース情報などをすべて取得するために、InnerExceptionがnullになるまで循環し続けることができます。

15
krillgar

要するに、しないでください。

あなたはこれを回避する方法を見つけることができると確信していますが、私は強くこのことに注意してください。 .NETの例外の元の設計に反します。例外は、ロギングを支援するためだけでなく、アプリケーション障害の元の原因に関する情報を提供します。

通常、最初のオプションを使用すると、元の例外のスタックトレースが維持されますが、別の例外にラップすることで追加情報を提供できます。私のコードでは、例外をログに記録するたびに、ログ機能がInnerExceptionプロパティを再帰的に処理して、エラーについて可能なあらゆる有用な情報を見つけます。

1
p.s.w.g