例外処理にtry catchを使用することがベストプラクティスです。


201

上級開発者であると主張する誰かからの私の同僚のコードを維持しながら、私はしばしば次のコードを見る:

try
{
  //do something
}
catch
{
  //Do nothing
}

または時々彼らは次のtry catchブロックのようなログファイルにログ情報を書き込みます

try
{
  //do some work
}
catch(Exception exception)
{
   WriteException2LogFile(exception);
}

彼らがやったことがベストプラクティスなのかと思っているだけです。私の考えでは、ユーザーがシステムで何が起こるかを知っている必要があるので、それは私を混乱させます。

アドバイスをください。


128
スニペット#1は許容できない時間の99.999%です。
leppie 2013

22
例外をユーザーに直接表示することは、主に次の2つの理由から、決して良い考えではありません。2.もし彼がいわゆる、ハッカーであるなら、彼は有用な情報を得るかもしれません。IMOのベストプラクティスは、例外をログに記録し、わかりやすいエラーメッセージを表示することです。
Leri

4
@leppie予期しない何かが発生した場合(NullReferenceまたはArgumentNullアプリケーションフローの一部ではない場合)は、修正が必要なバグが存在することを意味するため、ログを記録することでコードのデバッグを高速化できます。
2013

14
try-catchブロックを使用して例外を非表示にするのは、通常、遅延プログラミングの結果です。これは、入力をテストするための検証コードを記述する代わりによく使用されるショートカットです。ごくまれに、コードの操作に影響を与えない例外が発生する場合があります。このように非表示にしても問題はありません。ただし、これはかなりまれです。
コーリー

12
@Toan、まあ、バッチジョブの場合は、最上位(メイン)でログを記録してから、再度スローして、ジョブが異常終了したことを示すアラームを出します。それがWebアプリの場合、例外をグローバルハンドラーにバブルさせ、ログに記録してから、ユーザーをエラー画面にリダイレクトします。ユースケースシナリオでは、ログに記録したり、その他の方法で処理した後に、その例外をどのように処理するかを決定します。
アンソニー・ペグラム

回答:


300

私の例外処理戦略は:

  • にフックしてすべての未処理の例外をキャッチするにはApplication.ThreadException event、次のように決定します。

    • UIアプリケーションの場合:謝罪メッセージ(winforms)でユーザーにポップアップする
    • サービスまたはコンソールアプリケーションの場合:ファイルに記録します(サービスまたはコンソール)

次に、外部実行されるすべてのコードを常に囲みますtry/catch

  • Winformsインフラストラクチャによって発生したすべてのイベント(Load、Click、SelectedChanged ...)
  • サードパーティコンポーネントによって発生するすべてのイベント

次に、「try / catch」で囲みます

  • 私が知っているすべての操作が常に機能するとは限りません(IO操作、ゼロ除算の可能性のある計算...)。そのような場合、ApplicationException("custom message", innerException)実際に何が起こったかを追跡するために、新しいものを投げます

さらに、例外を正しく並べるように最善を尽くしています。次のような例外があります。

  • すぐにユーザーに表示する必要がある
  • カスケード問題を回避するために発生したときに物事をまとめるには、追加の処理が必要です(つまり、.EndUpdateをフィルfinally中にセクションに配置しますTreeView)。
  • ユーザーは気にしませんが、何が起こったかを知ることが重要です。だから私はいつもそれらを記録します:

    • イベントログ
    • またはディスク上の.logファイル

アプリケーションのトップレベルのエラーハンドラーで例外を処理するいくつかの静的メソッド設計することをお勧めします。

また、私は自分に以下のことを試みるよう強制します。

  • 覚えているすべての例外は、トップレベルにまで泡立てされています。すべての場所に例外ハンドラを配置する必要はありません。
  • 再利用可能な関数やディープコールされた関数は、例外を表示したりログに記録したりする必要はありません。これらの関数は、自動的にバブルアップされるか、例外ハンドラーでカスタムメッセージで再スローされます。

最後に:

悪い:

// DON'T DO THIS, ITS BAD
try
{
    ...
}
catch 
{
   // only air...
}

役に立たない:

// DONT'T DO THIS, ITS USELESS
try
{
    ...
}
catch(Exception ex)
{
    throw ex;
}

キャッチせずに最後に試してみるのは完全に有効です:

try
{
    listView1.BeginUpdate();

    // If an exception occurs in the following code, then the finally will be executed
    // and the exception will be thrown
    ...
}
finally
{
    // I WANT THIS CODE TO RUN EVENTUALLY REGARDLESS AN EXCEPTION OCCURED OR NOT
    listView1.EndUpdate();
}

トップレベルで私がすること:

// i.e When the user clicks on a button
try
{
    ...
}
catch(Exception ex)
{
    ex.Log(); // Log exception

    -- OR --

    ex.Log().Display(); // Log exception, then show it to the user with apologies...
}

いくつかの呼び出された関数で私がすること:

// Calculation module
try
{
    ...
}
catch(Exception ex)
{
    // Add useful information to the exception
    throw new ApplicationException("Something wrong happened in the calculation module :", ex);
}

// IO module
try
{
    ...
}
catch(Exception ex)
{
    throw new ApplicationException(string.Format("I cannot write the file {0} to {1}", fileName, directoryName), ex);
}

例外処理(カスタム例外)には多くのことがありますが、私が心掛けようとしているルールは、私が行う単純なアプリケーションには十分です。

キャッチされた例外を快適に処理するための拡張メソッドの例を次に示します。これらは一緒にチェーンできる方法で実装されており、独自のキャッチされた例外処理を追加するのは非常に簡単です。

// Usage:

try
{
    // boom
}
catch(Exception ex)
{
    // Only log exception
    ex.Log();

    -- OR --

    // Only display exception
    ex.Display();

    -- OR --

    // Log, then display exception
    ex.Log().Display();

    -- OR --

    // Add some user-friendly message to an exception
    new ApplicationException("Unable to calculate !", ex).Log().Display();
}

// Extension methods

internal static Exception Log(this Exception ex)
{
    File.AppendAllText("CaughtExceptions" + DateTime.Now.ToString("yyyy-MM-dd") + ".log", DateTime.Now.ToString("HH:mm:ss") + ": " + ex.Message + "\n" + ex.ToString() + "\n");
    return ex;
}

internal static Exception Display(this Exception ex, string msg = null, MessageBoxImage img = MessageBoxImage.Error)
{
    MessageBox.Show(msg ?? ex.Message, "", MessageBoxButton.OK, img);
    return ex;
}

98
catch(Exception ex) { throw ex; }C#では冗長性よりも悪いです(あなたがキャッチしている例外タイプに関係なく)。再スローするには、を使用しますthrow;。前者の場合、例外は自分から発生したように見えますthrow exが、後者の場合は、元のthrowステートメントから適切に発生します。
CVn

2
なぜあなたはフックんApplication.ThreadExceptionイベントをしてて、すべての例外をラップしますcatch(Exception ex) {ex.Log(ex);}。前者は優れた手法であると私はおそらく同意しますが、後者はエラーログを複製するリスクを追加し、例外が発生したことを隠します。またthrow ex、非常に悪いです。
キース

1
catch(Exception ex){throw ex;について理解しました。}役に立たない。したがって、「冗長」は「これを行わない」と述べるのに最適な言葉ではないと思います。そのため、私は投稿を少し変更して、最初の2つのトライキャッチの例を回避する必要があることを説明しました。
ラリー、

3
素晴らしく建設的な答え、何よりも私はOnly airというフレーズを楽しんだ:)そして、Application.ThreadExceptionイベントのおかげで、私はそれに気づかなかった。とても役に立った。
Mahdi Tahsildari 2014年


61

ベストプラクティスは、例外処理で問題が隠されないようにすることです。この意味はtry-catchブロックが非常にまれであることをます。

a try-catchを使用することが理にかなっている状況は3つあります。

  1. できる限り、既知の例外を常にローダウンします。ただし、例外が予想される場合は、通常、最初にそれをテストすることをお勧めします。たとえば、解析、フォーマット、および算術の例外は、特定のではなく、ほとんどの場合、最初にロジックチェックで処理する方が適切try-catchです。

  2. 例外に対して何かを行う必要がある場合(たとえば、トランザクションのロギングまたはロールバック)、例外を再度スローします。

  3. 常に未知のものに対処する、できる限り上位の例外をます。例外を消費し、再スローしない唯一のコードは、UIまたはパブリックAPIでなければなりません。

リモートAPIに接続しているとしましょう。ここでは、特定のエラーを予期している(そしてそのような状況では問題が発生する)ことがわかっているため、これはケース1です。

try 
{
    remoteApi.Connect()
}
catch(ApiConnectionSecurityException ex) 
{
    // User's security details have expired
    return false;
}

return true;

他の例外は予期されていないため、キャッチされないことに注意してください。

ここで、データベースに何かを保存しようとしていると想定します。失敗した場合はロールバックする必要があるため、ケース2があります。

try
{
    DBConnection.Save();
}
catch
{
    // Roll back the DB changes so they aren't corrupted on ANY exception
    DBConnection.Rollback();

    // Re-throw the exception, it's critical that the user knows that it failed to save
    throw;
}

例外を再度スローすることに注意してください。上位のコードは、何かが失敗したことを知る必要があります。

最後に、UIがあります。ここでは、完全に未処理の例外を設定する必要はありませんが、それらを非表示にする必要もありません。ここにケース3の例があります:

try
{
    // Do something
}
catch(Exception ex) 
{
    // Log exception for developers
    WriteException2LogFile(ex);

    // Display message to users
    DisplayWarningBox("An error has occurred, please contact support!");
}

ただし、ほとんどのAPIまたはUIフレームワークには、ケース3を実行する一般的な方法があります。たとえば、ASP.Netには、例外の詳細をダンプする黄色のエラー画面がありますが、運用環境ではより一般的なメッセージに置き換えることができます。エラー追跡と表示はハードコーディングするのではなく構成の決定にする必要があるため、多くのコードを節約できるため、これらに従うことはベストプラクティスです。

つまり、ケース1(既知の例外)とケース3(1回限りのUI処理)はどちらもより良いパターンを持っています(予想されるエラーやUIへのハンドエラー処理を回避します)。

ケース2でも、トランザクションスコープなどのより良いパターンに置き換えることができます(usingブロック中にコミットされていないトランザクションをロールバックするブロック)により、開発者がベストプラクティスのパターンを誤って取得することが難しくなります。

たとえば、大規模なASP.Netアプリケーションがあるとします。エラーロギングはELMAHを介して行うことができ、エラー表示はローカルで情報を提供するYSoDであり、本番環境ではローカライズされた素敵なメッセージである可能性があります。データベース接続はすべて、トランザクションのスコープとusingブロックを介して行うことができます。単一のtry-catchブロックは必要ありません。

TL; DR:ベストプラクティスは、実際にはtry-catchブロックをまったく使用しないことです。


4
@Jorjあなたは投稿全体を読むべきであり、それでも同意しない場合は、私の結論が気に入らないと述べるだけでなく、私の支持する議論の1つに対抗する方が建設的であろう。ほとんど常により良いパターンがあります。try-catchそれは(ごくまれに)役立つ場合があり、それらを使用してはいけないと主張しているわけではありませんが、99%の場合、より良い方法があります。
キース

断然ベストアンサー-ほぼすべての.net開発タイプには、グローバルレベルでの例外処理に非常に適した何らかのハンドラーがあり、一貫してそれらを処理するのが非常に簡単になるだけでなく、単純に失敗させることが非常に簡単になります開発中(なぜ誰がスタックトレースのログファイルを掘り下げたいのか?)@キース、私はあなたのTLDRを導き、グローバルハンドラーのいくつかの例(つまり、ThreadException、Application_Errorなど)を追加します。必ず特定のエラーをキャッチしますが、これまでのメソッドをtry / catch / logにラップするのはおかしい
b_levitt

34

例外はブロッキングエラーです。

まず第一に、ベストプラクティスは、ブロッキングエラーでない限り、あらゆる種類のエラーに対して例外をスローしないことです。です。

エラーがブロックしている場合、例外をスローします。例外が既にスローされている場合は、例外であるため、非表示にする必要はありません。ユーザーにそのことを知らせます(UIで、例外全体をユーザーにとって有用なものに再フォーマットする必要があります)。

ソフトウェア開発者としてのあなたの仕事は、いくつかのパラメーターまたはランタイム状況が例外で終了する可能性がある例外的なケースを防ぐように努めることです。つまり、例外をミュートしてはいけませんが、これらは回避する必要があります

たとえば、一部の整数入力に無効な形式が含まれる可能性があることがわかっている場合は、int.TryParse代わりにint.Parse。「失敗した場合は単に例外をスローする」とだけ言うのではなく、これを実行できるケースがたくさんあります。

例外のスローは高価です。

結局のところ、例外がスローされた場合、いったんスローされたログにログを書き込むのではなく、ベストプラクティスの1つは、初回例外ハンドラでキャッチすることです。例えば:

  • ASP.NET:Global.asaxののApplication_Error
  • その他:AppDomain.FirstChanceExceptionイベント

私のスタンスは、ローカルのtry / catchesは、例外を別の例外に変換する可能性がある特別なケース、または非常に、非常に、非常に非常に非常に特別なケース(ライブラリバグバグ全体を回避するためにミュートする必要がある無関係な例外をスローします)。

残りの場合:

  • 例外を避けてください。
  • これが不可能な場合:初回例外ハンドラー。
  • または、PostSharpアスペクト(AOP)を使用します。

コメントで@thewhiteambitに答える...

@thewhiteambitさんのコメント:

例外は致命的なエラーではなく、例外です。時々それらはエラーでさえないが、それらを考慮することは致命的エラーは例外が何であるかについて完全に誤った理解である。

まず、どのようにして例外がエラーになることはありませんか?

  • データベース接続なし=>例外。
  • あるタイプに解析するための無効な文字列フォーマット=>例外
  • JSONを解析しようとしていますが、入力は実際にはJSON =>例外ではありません
  • nullオブジェクトが期待されている間の引数=>例外
  • 一部のライブラリにはバグがあります=>予期しない例外をスローします
  • ソケット接続があり、切断されます。次に、メッセージを送信しようとします=>例外
  • ...

例外がスローされた場合の1kのケースをリストする場合があり、結局のところ、考えられるケースのいずれかがエラーになります

例外エラーです。1日の終わりにそれは診断情報を収集するオブジェクトであるためです。これにはメッセージがあり、何かがうまくいかないときに発生します。

例外的なケースがない限り、誰も例外をスローしません。例外がスローされると、例外をブロックする必要があります。制御フローを実装するためにtry / catchと例外を使用しないと、アプリケーション/サービスが例外的なケースに入った操作を停止するためです。

また、Martin Fowlerが発行した(Jim Shoreが作成した)フェイルファストパラダイムをすべての人に確認することをお勧めします。これは、少し前にこのドキュメントに到達する前でも、常に例外の処理方法を理解していた方法です。

[...]致命的エラーとは、例外とは何かについての完全な誤解です。

通常、例外一部の操作フローを削減し、人間が理解できるエラーに変換するように処理されます。したがって、例外は実際にはエラーのケースを処理し、アプリケーション/サービスの完全なクラッシュを回避してユーザー/コンシューマに問題が発生したことを通知するために取り組むためのより良いパラダイムのようです。

@thewhiteambitの懸念に関するその他の回答

たとえば、Database-Connectionが見つからない場合、プログラムは例外的にローカルファイルへの書き込みを続行し、データベースが再び利用可能になったときに変更をデータベースに送信できます。無効な文字列から数値へのキャストは、Parse( "1,5")へのデフォルトの英語を試すのに失敗し、完全にドイツ語の解釈でもう一度試すように、例外で言語ローカルの解釈を使用して再度解析しようとする可能性があります。区切り記号としてポイントの代わりにカンマを使用しているため、問題ありません。これらの例外はブロッキングであってはならず、いくつかの例外処理のみが必要であることがわかります。

  1. データをデータベースに永続化せずにアプリがオフラインで動作する可能性がある場合は、例外を使用しないでください。使用し制御フローを実装することtry/catchはアンチパターンと見なされます。オフラインでの作業は考えられるユースケースであるため、データベースにアクセスできるかどうかを確認するための制御フローを実装し、到達不能になるまで待機しません

  2. 解析することも予想される場合(あるCASE例外ではありません)。これが予想される場合は、例外を使用してフローを制御しないでください。。ユーザーからメタデータを取得して、彼/彼女の文化が何であるかを知り、フォーマッターを使用します!.NETはこの環境と他の環境もサポートしますアプリケーション/サービスのカルチャ固有の使用法が予想される場合は数値のフォーマットを回避する必要があるため、例外があります

未処理の例外は通常エラーになりますが、例外自体はcodeproject.com/Articles/15921/Not-All-Exceptions-Are-Errorsではありません

この記事は、著者の意見または見解です。

ウィキペディアも記事の著者の意見にすぎない可能性があるので、私はそれはそうではありません がドグマであるが、例外によるコーディングの記事がいくつかの段落のどこかで言っていることを確認してください:

[...]これらの例外を使用して、プログラムを続行するために発生する特定のエラーを処理することを、例外によるコーディングと呼びます。このアンチパターンは、ソフトウェアのパフォーマンスと保守性をすぐに低下させる可能性があります。

それはまたどこかで言う:

誤った例外の使用法

多くの場合、例外によるコーディングは、誤った例外の使用を伴うソフトウェアのさらなる問題につながる可能性があります。一意の問題に対して例外処理を使用することに加えて、不正な例外の使用は、例外が発生した後でもコードを実行することにより、これをさらに進めます。この貧弱なプログラミング方法は、多くのソフトウェア言語のgotoメソッドに似ていますが、ソフトウェアの問題が検出された後にのみ発生します。

正直なところ、ソフトウェアを開発することはできませんが、ユースケースを真剣に受け止めていないと思います。あなたがそれを知っているなら...

  • データベースがオフラインになる可能性があります...
  • 一部のファイルはロックできます...
  • 一部のフォーマットがサポートされていない可能性があります...
  • 一部のドメイン検証が失敗する可能性があります...
  • アプリはオフラインモードで動作するはずです...
  • どんなユースケースでも ...

... そのために例外を使用しません。あなたはサポートします、通常の制御フローを使用して、これらのユースケースを。

また、予期しない使用例がカバーされていない場合、例外がスローされるため、コードはすぐに失敗します。そうです、例外は例外的なケースだからです。

一方では、最終的に、時にはあなたはカバー例外的なケース投げ期待例外をしますが、制御フローを実装するためにそれらをスローしません。これは、一部のユースケースをサポートしていないこと、またはコードが特定の引数または環境データ/プロパティで機能しないことを上位レイヤーに通知するためです。


6

ユーザーがコードで発生したことについて心配する必要があるのは、問題を回避するためにユーザーが実行できること、または実行する必要があることだけです。フォームのデータを変更できる場合は、問題を回避するためにボタンを押すか、アプリケーションの設定を変更してから、通知してください。ただし、ユーザーが回避できない警告またはエラーは、製品に対する信頼を失うだけです。

例外とログは、開発者であり、エンドユーザーではありません。各例外をキャッチするときに行うべき正しいことを理解することは、いくつかのゴールデンルールを適用したり、アプリケーション全体のセーフティネットに依存したりするよりもはるかに優れています。

マインドレスコーディングは、唯一の種類の誤ったコーディングです。それらの状況で実行できるより良い何かがあると感じているという事実は、優れたコーディングに投資していることを示していますが、これらの状況でいくつかの一般的なルールをスタンプすることを避け、最初に何かをスローする理由とその内容を理解するあなたはそれから回復するために行うことができます。


6

私はこれが古い質問であることを知っていますが、MSDNの記事について誰も触れておらず、実際にそれを明確にしたのはこのドキュメントでした。MSDNにはこれに関する非常に優れたドキュメントがあり、次の条件に該当する場合は例外をキャッチする必要があります。

  • 例外がスローされる理由を十分に理解しており、FileNotFoundExceptionオブジェクトをキャッチしたときにユーザーに新しいファイル名の入力を求めるなど、特定の回復を実装できます。

  • より具体的な新しい例外を作成してスローできます。

int GetInt(int[] array, int index)
{
    try
    {
        return array[index];
    }
    catch(System.IndexOutOfRangeException e)
    {
        throw new System.ArgumentOutOfRangeException(
            "Parameter index is out of range.");
    }
}
  • 追加の処理のために渡す前に、例外を部分的に処理したい。次の例では、catchブロックを使用して、例外を再スローする前にエラーログにエントリを追加します。
    try
{
    // Try to access a resource.
}
catch (System.UnauthorizedAccessException e)
{
    // Call a custom error logging procedure.
    LogError(e);
    // Re-throw the error.
    throw;     
}

例外と例外処理」セクション全体と、例外のベストプラクティスを読むことをお勧めします


1

より良い方法は、2番目の方法(例外タイプを指定する方法)です。これの利点は、このタイプの例外がコードで発生する可能性があることを知っていることです。このタイプの例外を処理しており、再開できます。他の例外が発生した場合、それは何か問題があり、コード内のバグを見つけるのに役立ちます。アプリケーションは最終的にクラッシュしますが、修正する必要のある見逃したもの(バグ)があることがわかります。


1

例外を除いて、私は以下を試します:

まず、ゼロによる除算、IO操作などの特殊な例外をキャッチし、それに応じてコードを記述します。たとえば、ゼロによる除算は、ユーザーに警告できる値の根拠に応じて(中間の計算(引数ではなく)の単純な計算機がゼロによる除算に到着する例)または警告なしにその例外を処理し、ログに記録しますそれを処理し続けます。

次に、残りの例外をキャッチしてログに記録します。可能であればコードの実行を許可します。それ以外の場合は、エラーが発生したことをユーザーに警告し、エラーレポートをメールで送信するように依頼します。

コードでは、このようなもの:

try{
    //Some code here
}
catch(DivideByZeroException dz){
    AlerUserDivideByZerohappened();
}
catch(Exception e){
    treatGeneralException(e);
}
finally{
    //if a IO operation here i close the hanging handlers for example
}

1
ゼロによる除算の例外などは0、ではなく、事前に分子をチェックすることでより適切に処理されtry-catchます。また、なぜExceptionここでジェネリックを捕まえるのですか?エラーを予期しないすべてのケースでここで処理するよりも、エラーをバブルアップさせた方がよいでしょう。
キース

私が挙げた例について私が書いたことをよく読んでください。「引数にはない」ことに注意してください。もちろん、計算機は与えられた引数を検証する必要があります。私が話したのは中途段階についてでした。この時点で、ユーザー引数の検証はすでに行われています。また、一部のアプリケーションでは、例外が発生しないようにするのが適切です。一部のアプリは例外をサイレントで処理する必要があり、他のアプリは例外をエラーとして処理する必要があります。たとえば、Webサーバーは例外が発生した場合でも実行する必要があり、医療ソフトウェア(X線装置など)は例外が発生した場合に中止する必要があります。
Sorcerer86pt

何のアプリが必要があり、これまで黙って例外を処理しません。場合によっては、コードが処理できる例外がありますが、そのような使用法はまれであり、予期される例外に固有である必要があります。Webサーバーの例は適切ではありません。エラーのログ方法と、詳細またはHTTP 500ページのみで表示するかどうかを選択できる構成設定が必要ですが、暗黙のうちにエラーを無視してはなりません
キース

「goto」の同義語をもう1つ追加しようとする人々を本当に動機付けているものを理解しようとしています。しかし、ゼロによる除算に関しては、これは言語の強化を正当化する私が見ることができる1つのタイプの例外です。どうして?それは、A)ゼロが統計的にデータセット内で微小な場合であり、B)例外を使用する(許可する)ことは、除算を行うことがゼロ除数をテストする1つの方法であるため、はるかに効率的な場合があるためです。AとBがtrueの場合、例外を使用するとプログラムの平均実行速度が速くなり、さらに小さくなる可能性があります。
マイク・レイトン

1

2番目の方法は良い方法です。

エラーを表示したくない場合、アプリケーションに関連しないランタイム例外(エラー)を表示してアプリケーションのユーザーを混乱させたい場合は、エラーをログに記録するだけで、技術チームが問題を探して解決できます。

try
{
  //do some work
}
catch(Exception exception)
{
   WriteException2LogFile(exception);//it will write the or log the error in a text file
}

アプリケーション全体に対して2番目のアプローチをとることをお勧めします。


2
2番目のアプローチは、エラーが発生したことをユーザーに表示しません。たとえば、ユーザーが何かを保存していて、失敗したことを知らない場合などです。catchブロックは常にthrow、例外を起動するために呼び出すか、アクションが失敗したことをユーザーに知らせる何かを返す/何かを表示する必要があります。あなたはそれが何であれ保存に失敗したとき、彼らがそれを取得しようとしてそれを見つけることができないときから6か月後ではなく、サポート呼び出しを受けたいと思っています。
キース

0

空白のキャッチブロックを残すことは、悪いことです。エラーが発生した場合の対処法は次のとおりです。

  1. ファイル\データベースなどにログインします。
  2. その場で修正してみてください(おそらくその操作を実行する別の方法を試してください)
  3. それを修正できない場合は、エラーがあることをユーザーに通知し、当然操作を中止します

0

私にとって、例外処理はビジネスルールと見なすことができます。明らかに、最初のアプローチは受け入れられません。2番目の方が優れており、コンテキストがそうだとすれば、100%正しい方法かもしれません。たとえば、たとえば、Outlookアドインを開発しているとします。アドインが未処理の例外をスローする場合、1つのプラグインが失敗したためにOutlookがそれ自体を破壊しないため、Outlookユーザーはそれを知る可能性があります。そして、あなたは何がうまくいかなかったかを理解するのに苦労しています。したがって、この場合の2番目のアプローチは、私にとっては正しいアプローチです。例外をログに記録するだけでなく、ユーザーにエラーメッセージを表示することもできます-私はそれをビジネスルールと見なします。


0

ベストプラクティスは、エラーが発生したときに例外をスローすることです。エラーが発生したため、非表示にしないでください。

しかし、実際には、これを非表示にしたい場合、いくつかの状況が考えられます

  1. サードパーティのコンポーネントに依存していて、エラーが発生した場合にプログラムを続行します。
  2. エラーが発生した場合に続行する必要があるビジネスケースがあります。

6
いいえ投げないでくださいExceptionずっと。必要なExceptionすべての適切なサブクラスをスローしますが、Exceptionセマンティック情報がまったく提供されないためです。投げるのは理にかなっているExceptionが、そのサブクラスではないシナリオはまったく見当たらない
からCVn


0

catch引数のないは単に例外を食べているだけであり、役に立たない。致命的なエラーが発生した場合はどうなりますか?引数なしでcatchを使用した場合に何が起こったかを知る方法はありません。

catchステートメントは、より多くのキャッチする必要があり、特定のような例外をFileNotFoundExceptionし、その後に非常に終わり、あなたがキャッチしなければならないException他の例外をキャッチし、それらをログ思われます。


catch(Exception)最後に将軍がいるのはなぜですか?期待していない場合は、常に次のレイヤーに渡すことをお勧めします。
キース

1
@Keithはい、あなたは...あなたが期待されていませんが、あなたは目的を記録するための一般的な例外をキャッチできることを例外にはポイントが...すぐそこですされていません
Anirudha

0

ユーザーに何も言わない例外を処理する必要がある場合があります。

私のやり方は:

  • 重要な例外について、アプリケーションレベルで(つまりglobal.asaxで)キャッチされない例外をキャッチする(アプリケーションは役に立たない)。これらの例外は、私がその場所でキャッチしていません。アプリレベルでそれらを記録し、システムにその仕事をさせてください。
  • 「その場で」キャッチして、ユーザーにいくつかの有用な情報を表示します(間違った番号を入力すると、解析できません)。
  • その場でキャッチし、「バックグラウンドで更新情報を確認しますが、サービスが実行されていない」などの限界的な問題については何もしません。

それは間違いなくベストプラクティスである必要はありません。;-)


0

私はあなたに何かを伝えることができます:

例外を無視しているため、スニペット#1は受け入れられません。(何も起こらなかったように飲み込んでいます)。

したがって、何もしないか、単に再スローするだけのcatchブロックを追加しないでください。

Catchブロックはいくつかの値を追加する必要があります。たとえば、エンドユーザーへの出力メッセージやエラーのログ。

通常のフロープログラムロジックでは例外を使用しないでください。例えば:

たとえば、入力の検証。<-これは有効な例外的な状況ではなく、IsValid(myInput);入力項目が有効かどうかを確認するメソッドを記述する必要があります。

例外を回避するようにコードを設計します。例えば:

int Parse(string input);

解析できない値をintに渡すと、このメソッドは例外をスローし、代わりに次のように記述します。

bool TryParse(string input,out int result); <-このメソッドは、解析が成功したかどうかを示すブール値を返します。

たぶん、これはこの質問の範囲から少し外れていますが、これがtry {} catch(){}例外や例外について正しい判断を下すのに役立つことを願っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.