CA1031:不要捕捉一般异常类型

属性
规则 ID CA1031
标题 不要捕捉一般异常类型
类别 设计
修复是中断修复还是非中断修复 非中断
在 .NET 8 中默认启用

原因

catch 语句中捕捉到了 System.ExceptionSystem.SystemException 等一般异常,或者已使用一般 catch 子句(如 catch())。

默认情况下,此规则仅标记要捕捉的一般异常类型,但这是可配置的

规则说明

不应捕捉一般异常。

如何解决冲突

若要解决此规则中的冲突,请捕捉更具体的异常,或者在执行 catch 块中的最后一条语句时重新引发一般异常。

何时禁止显示警告

不禁止显示此规则发出的警告。 捕获一般异常类型可隐藏库用户的运行时问题,并且可能会使调试变得更加困难。

注意

从 .NET Framework 4 开始,公共语言运行时 (CLR) 不再提供操作系统和托管代码中发生的损坏状态异常(例如,Windows 中的访问冲突),然后由托管代码来处理。 如果要在 .NET Framework 4 或更高版本中编译某个应用程序,并保留对损坏状态异常的处理,则可将 HandleProcessCorruptedStateExceptionsAttribute 特性应用于负责处理损坏状态异常的方法。

配置代码以进行分析

使用下面的选项来配置代码库的哪些部分要运行此规则。

可以仅为此规则、为适用的所有规则或为适用的此类别(设计)中的所有规则配置此选项。 有关详细信息,请参阅代码质量规则配置选项

不允许的异常类型名称

可配置不允许捕捉哪些异常类型。 例如,若要指定规则应使用 NullReferenceException 标记 catch 处理程序,请将以下键值对添加到项目的 editorconfig 文件中:

dotnet_code_quality.CA1031.disallowed_symbol_names = NullReferenceException

选项值中允许的类型名称格式(用 | 分隔):

  • 仅类型名称(包括具有相应名称的所有符号,不考虑包含的类型或命名空间)
  • 完全限定的名称,使用符号的文档 ID 格式,前缀为 T:

示例:

选项值 总结
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:再次引发以保留堆栈详细信息