CA1031:不要捕捉一般异常类型
属性 | 值 |
---|---|
规则 ID | CA1031 |
标题 | 不要捕捉一般异常类型 |
类别 | 设计 |
修复是中断修复还是非中断修复 | 非中断 |
在 .NET 8 中默认启用 | 否 |
原因
在 catch
语句中捕捉到了 System.Exception 或 System.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;
}
}
}