CA2200: следует повторно вызывать исключение для сохранения сведений о стеке
Свойство | Значение |
---|---|
Идентификатор правила | CA2200 |
Заголовок | Повторно порождайте исключения для сохранения сведений стека |
Категория | Использование |
Исправление является критическим или не критическим | Не критическое |
Включен по умолчанию в .NET 9 | Как предупреждение |
Причина
В операторе throw
повторно вызывается и явным образом задается исключение.
Описание правила
При возникновении исключения часть информации в нем представляет собой трассировку стека. Трассировка стека — это список иерархии вызовов методов, который начинается с метода, вызывающего исключение, и завершается методом, перехватывающим исключение. Если исключение выполняется повторно, указав исключение в throw
инструкции, трассировка стека перезапускается в текущем методе, а список вызовов методов между исходным методом, который вызвал исключение, и текущий метод теряется. Для сохранения исходных данных трассировки стека с исключением следует использовать оператор throw
без указания исключения.
Если вы выполняете повторное создание исключения из другого места, отличного от обработчика (catch
блок), используйте ExceptionDispatchInfo.Capture(Exception) для записи исключения в обработчике и ExceptionDispatchInfo.Throw() при необходимости повторного его увеличения.
Дополнительные сведения см. в разделе "Запись и повторное создание исключений".
Устранение нарушений
Чтобы устранить нарушение этого правила, повторно вызывайте это исключение без его явного указания.
Когда лучше отключить предупреждения
Для этого правила отключать вывод предупреждений не следует.
Пример
В следующем примере показан метод, CatchAndRethrowExplicitly
который нарушает правило и метод, CatchAndRethrowImplicitly
который удовлетворяет правилу.
class TestsRethrow
{
static void Main2200()
{
TestsRethrow testRethrow = new TestsRethrow();
testRethrow.CatchException();
}
void CatchException()
{
try
{
CatchAndRethrowExplicitly();
}
catch (ArithmeticException e)
{
Console.WriteLine($"Explicitly specified:{Environment.NewLine}{e.StackTrace}");
}
try
{
CatchAndRethrowImplicitly();
}
catch (ArithmeticException e)
{
Console.WriteLine($"{Environment.NewLine}Implicitly specified:{Environment.NewLine}{e.StackTrace}");
}
}
void CatchAndRethrowExplicitly()
{
try
{
ThrowException();
}
catch (ArithmeticException e)
{
// Violates the rule.
throw e;
}
}
void CatchAndRethrowImplicitly()
{
try
{
ThrowException();
}
catch (ArithmeticException)
{
// Satisfies the rule.
throw;
}
}
void ThrowException()
{
throw new ArithmeticException("illegal expression");
}
}
Imports System
Namespace ca2200
Class TestsRethrow
Shared Sub Main2200()
Dim testRethrow As New TestsRethrow()
testRethrow.CatchException()
End Sub
Sub CatchException()
Try
CatchAndRethrowExplicitly()
Catch e As ArithmeticException
Console.WriteLine("Explicitly specified:{0}{1}",
Environment.NewLine, e.StackTrace)
End Try
Try
CatchAndRethrowImplicitly()
Catch e As ArithmeticException
Console.WriteLine("{0}Implicitly specified:{0}{1}",
Environment.NewLine, e.StackTrace)
End Try
End Sub
Sub CatchAndRethrowExplicitly()
Try
ThrowException()
Catch e As ArithmeticException
' Violates the rule.
Throw e
End Try
End Sub
Sub CatchAndRethrowImplicitly()
Try
ThrowException()
Catch e As ArithmeticException
' Satisfies the rule.
Throw
End Try
End Sub
Sub ThrowException()
Throw New ArithmeticException("illegal expression")
End Sub
End Class
End Namespace