CA1031: 一般的な例外の種類はキャッチしません

プロパティ
ルール ID CA1031
Title 一般的な例外の種類はキャッチしません
[カテゴリ] デザイン
修正が中断ありか中断なしか なし
.NET 8 では既定で有効 いいえ

原因

System.ExceptionSystem.SystemException などの一般的な例外は、catch ステートメントでキャッチされるか、catch() などの一般的な Catch 句が使用されます。

既定では、この規則は、キャッチされた一般的な例外の種類にのみフラグを設定しますが、これは構成可能です。

規則の説明

汎用的な例外はキャッチしないでください。

違反の修正方法

この規則違反を修正するには、より具体的な例外をキャッチするか、catch ブロックの最後のステートメントとして一般的な例外をスローし直します。

どのようなときに警告を抑制するか

この規則による警告は抑制しないでください。 一般的な種類の例外をキャッチすると、実行時の問題がライブラリ ユーザーの目に入りづらくなり、デバッグがより困難になります。

メモ

.NET Framework 4 以降、共通言語ランタイム (CLR) により、Windows でのアクセス違反などの、オペレーティング システムやマネージド コードで発生する破損状態例外が、マネージド コードで処理するように配信されなくなりました。 .NET Framework 4 以降のバージョンでアプリケーションをコンパイルし、破損状態例外の処理を維持する場合は、破損状態例外を処理するメソッドに HandleProcessCorruptedStateExceptionsAttribute 属性を適用します。

分析するコードを構成する

次のオプションを使用して、コードベースのどの部分に対してこの規則を実行するか構成します。

このオプションを構成できる対象は、この規則だけ、それを適用するすべての規則、それを適用するこのカテゴリ (デザイン) のすべての規則のいずれかです。 詳細については、「コード品質規則の構成オプション」を参照してください。

禁止されている例外の種類の名前

キャッチしない例外の種類を構成できます。 たとえば、NullReferenceException が使用された catch ハンドラーにフラグを設定する規則を指定するには、自分のプロジェクトの .editorconfig ファイルに次のキーと値のペアを追加します。

dotnet_code_quality.CA1031.disallowed_symbol_names = NullReferenceException

オプション値で使用できる型名の形式 (| で区切ります):

  • 型名のみ (包含する型または名前空間に関係なく、その名前が指定されたすべてのシンボルが含まれます)
  • T: のプレフィックスが付いた、そのシンボルのドキュメント ID 形式の完全修飾名。

次に例を示します。

オプションの値 まとめ
dotnet_code_quality.CA1031.disallowed_symbol_names = ExceptionType コンパイル内の 'ExceptionType' という名前のすべてのシンボルと一致します。
dotnet_code_quality.CA1031.disallowed_symbol_names = ExceptionType1|ExceptionType2 コンパイル内の 'ExceptionType1' または 'ExceptionType2' のいずれかの名前のすべてのシンボルと一致します。
dotnet_code_quality.CA1031.disallowed_symbol_names = T:NS.ExceptionType 特定の完全修飾名の 'ExceptionType ' という名前の特定の型と一致します
dotnet_code_quality.CA1031.disallowed_symbol_names = T:NS1.ExceptionType1|T:NS1.ExceptionType2 それぞれの完全修飾名の 'ExceptionType1' と 'ExceptionType2' という名前の型と一致します。

これらのオプションを構成できる対象は、この規則だけ、それを適用するすべての規則、それを適用するこのカテゴリ (デザイン) のすべての規則のいずれかです。 詳細については、「コード品質規則の構成オプション」を参照してください。

次は、この規則に違反している型と、catch ブロックが正しく実装されている型の例を示しています。

Imports System
Imports System.IO

Namespace ca1031

    ' Creates two violations of the rule.
    Public Class GenericExceptionsCaught

        Dim inStream As FileStream
        Dim outStream As FileStream

        Sub New(inFile As String, outFile As String)

            Try
                inStream = File.Open(inFile, FileMode.Open)
            Catch ex As SystemException
                Console.WriteLine("Unable to open {0}.", inFile)
            End Try

            Try
                outStream = File.Open(outFile, FileMode.Open)
            Catch
                Console.WriteLine("Unable to open {0}.", outFile)
            End Try

        End Sub

    End Class

    Public Class GenericExceptionsCaughtFixed

        Dim inStream As FileStream
        Dim outStream As FileStream

        Sub New(inFile As String, outFile As String)

            Try
                inStream = File.Open(inFile, FileMode.Open)

                ' Fix the first violation by catching a specific exception.
            Catch ex As FileNotFoundException
                Console.WriteLine("Unable to open {0}.", inFile)
                ' For functionally equivalent code, also catch the
                ' remaining exceptions that may be thrown by File.Open
            End Try

            Try
                outStream = File.Open(outFile, FileMode.Open)

                ' Fix the second violation by re-throwing the generic 
                ' exception at the end of the catch block.
            Catch
                Console.WriteLine("Unable to open {0}.", outFile)
                Throw
            End Try

        End Sub

    End Class

End Namespace
// Creates two violations of the rule.
public class GenericExceptionsCaught
{
    FileStream? inStream;
    FileStream? outStream;

    public GenericExceptionsCaught(string inFile, string outFile)
    {
        try
        {
            inStream = File.Open(inFile, FileMode.Open);
        }
        catch (SystemException)
        {
            Console.WriteLine("Unable to open {0}.", inFile);
        }

        try
        {
            outStream = File.Open(outFile, FileMode.Open);
        }
        catch
        {
            Console.WriteLine("Unable to open {0}.", outFile);
        }
    }
}

public class GenericExceptionsCaughtFixed
{
    FileStream? inStream;
    FileStream outStream;

    public GenericExceptionsCaughtFixed(string inFile, string outFile)
    {
        try
        {
            inStream = File.Open(inFile, FileMode.Open);
        }

        // Fix the first violation by catching a specific exception.
        catch (FileNotFoundException)
        {
            Console.WriteLine("Unable to open {0}.", inFile);
        };

        // For functionally equivalent code, also catch 
        // remaining exceptions that may be thrown by File.Open

        try
        {
            outStream = File.Open(outFile, FileMode.Open);
        }

        // Fix the second violation by rethrowing the generic 
        // exception at the end of the catch block.
        catch
        {
            Console.WriteLine("Unable to open {0}.", outFile);
            throw;
        }
    }
}

CA2200: スタック詳細を保持するために再度スローします