4

この MSDN の記事によると、一般的な例外をキャッチするべきではありません。それを扱うstackoverflowの質問があると確信しています.なぜそれが良い習慣ではないのか理解していますが、今日の別のMSDN記事でこの例を見ました:

using System;
using System.IO;

class Test
{
    public static void Main()
    {
        try
        {
            using (StreamReader sr = new StreamReader("TestFile.txt"))
            {
                String line = sr.ReadToEnd();
                Console.WriteLine(line);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("The file could not be read:");
            Console.WriteLine(e.Message);
        }
    }
}

その例で一般的な例外をキャッチする正当な理由はありますか?それとも、特定の例外をすべてキャッチする例を書くのが面倒だったからですか?

4

3 に答える 3

2

この場合、これはであり、MSDNの多くのコード例と同様に、その点では不十分です。

これは、基本クラスではなく IO Exception をキャッチする必要があります。

キャッチするのが理にかなっている唯一の場所Exceptionは、ログを記録するためのグローバル例外ハンドラーです。

于 2012-10-12T09:31:01.127 に答える
1

ルール「CA1031: 一般的な例外タイプをキャッチしない」はまったく役に立ちません。(それ自体は意図ではなく、実装と説明です)

この特定のケースでは、コンストラクターがスローすることが文書化されている例外の「ほとんど」をカバーするため、より具体的なものをキャッチすることが実行可能である可能性があります。IOExceptionStreamReader

(ああ、待ってください。それから、によってスローされる可能性のあるすべてのものも考慮に入れる必要がありますReadToEnd

(ああ、待ってください。渡された文字列が空の場合に備えて、正当な例外キャッチ ケースがあるのか​​もしれません。つまり、それを明示的にテストするのではなく、一般的にキャッチしたいのです。)ArgumentException

それ以外で:

  • 任意の関数からスローされる可能性のある例外のセットは次のとおりです。

    1. 多くの場合、不十分に文書化されています
    2. OutOfMemoryException無制限の可能性があります (他の例外につながる実装のバグなど、いくつか潜んでいる可能性があります)。
    3. ほとんど無関係です (いくつかのバグキャッチのようなものを法としてArgumentNullException)

与えられた例を大まかに考えると、気にするのはファイルの読み取りが失敗したことだけです-IFFが失敗した場合は、呼び出しチェーンでそれを伝える必要があります。

繰り返します:ファイルの読み取りが失敗したこと、およびその理由が二次的なものであることをコール チェーンに伝えたいと考えています。

ファイルの読み取り (処理) が失敗したとき:例外がスローされたとき。

したがって、本当にやりたいことは、例外をキャッチし、やりたいことでコンテキスト化して (たとえば、ファイル名を追加して)、何がうまくいかなかったのか、なぜうまくいかなかったのかを示す何かを返すか再スローすることです(それは実際の "内部」例外)。

このため、例は(ほぼ)スポットです:

  • この場合の「コール チェーンを上る」とは、ユーザーが直接コンソールにいることです。
  • エラーを「ユーザー」が読み取る文字列として「返し」ます。これは、単純なコンソールプログラムに適しています。
  • 何がうまくいかなかったのかを明確に伝えます。(ただし、渡されたファイル名を含める必要がありますStreamReader。)
  • 失敗した理由、つまり例外メッセージが含まれています。(コール スタックも含める必要がある可能性があります。)

例:

この例はもう少し複雑で、ファイル名はユーザーが指定したものだとします。空の文字列は、(a) 通常のケースであり、おそらく (b)コードでの特別な処理を保証しないユーザー エラーです。完全に十分です。

上で推奨されているようにキャッチするだけIOExceptionでは、ユーザーが空のファイル名を入力すると、アプリケーションがクラッシュするか、他の catch ブロックと本質的に同じことを行う追加の catch ブロックが必要になります: ファイルの読み取りが失敗したこととその理由を報告します。


独立した観察: この素晴らしい作品を見つけました: http://www.codeproject.com/Articles/7557/Exception-Handling-in-C-with-the-quot-Do-Not-Catchここで、著者は確かに私よりも建設的です「まったく役に立たない」ステートメントですが、本質的に同様の結論があります(別の、確かに有効な解決策があります):(emph。追加)

Microsoft のガイドラインに従う場合、File.Copyメソッドによってトリガーされる可能性のある例外のみをキャッチする必要があります。.NET Framework のクラス ライブラリを見ると、これが UnauthorizedAccessException (...) であることがわかります。あなたが私に尋ねると、これらすべての例外を個別にキャッチすることはできません。私が知りたかったのは、ファイルのコピーが失敗したかどうかだけです。IOException、ArgumentException、および NotSupportedException (他のすべての例外はこれら 3 つの例外から派生するため) のみをキャプチャするだけで十分ですが、これを知るにはドキュメントをもう一度読む必要があります。単純にファイルをコピーするのに、それほど苦労したくありません。

ガイドラインは、実行されたタスクによってスローされる可能性のあるすべての例外を知っていることを前提としています。ファイルのコピーは、Microsoft によって適切に文書化されている非常に単純な操作です。しかし、サードパーティのツールを使用している場合はどうなるでしょうか? 無人ツールの安定性は、このツールのドキュメントの品質に依存します。このサードパーティが、ツールがスローする例外の 1 つをドキュメントに記載するのを忘れた場合、無人アプリケーションが途中で停止する可能性があります。

于 2014-12-09T15:36:25.413 に答える
0

例は明確かつ単純でなければなりません。これは、明確で単純な例の例です。しかし、コードで一般的な例外をキャッチするべきではありません。

于 2012-10-12T09:31:14.367 に答える