CA1502: избегайте чрезмерной сложности

Свойство Значение
Идентификатор правила CA1502
Заголовок Избегайте чрезмерной сложности
Категория Ремонтопригодность
Исправление является критическим или не критическим Не критическое
Пороговое значение по умолчанию 25
Включен по умолчанию в .NET 8 No

Причина

Метод имеет чрезмерную цикломатическую сложность.

Описание правила

Цикломатическая сложность измеряет число линейно независимых путей в методе, которое определяется числом и сложностью условных ветвей. Низкая цикломатическая сложность обычно указывает, что метод прост в понимании, тестировании и обслуживании. Цикломатическая сложность вычисляется на основе графа потока управления метода следующим образом:

цикломатическая сложность = количество краев − количество узлов + 1

Узел представляет логическую точку ветвления, а край — линию между узлами.

Правило сообщает о нарушении, когда цикломатическая сложность метода превышает 25. Однако можно настроить пороговое значение , а также указать другие типы символов, которые должен анализировать правило.

Дополнительные сведения о метриках кода см. в разделе Измерение сложности управляемого кода.

Устранение нарушений

Для устранения нарушения этого правила выполните рефакторинг метода, чтобы уменьшить его цикломатическую сложность.

Когда лучше отключить предупреждения

Вы можете отключить предупреждение из этого правила, если сложность уменьшить затруднительно, а метод прост в понимании, тестировании и обслуживании. В частности, можно подумать об отключении для метода, содержащего большую инструкцию switch (Select в Visual Basic). Риск дестабилизации базы кода на последующих этапах цикла разработки или внесение неожиданных изменений в поведение во время выполнения в ранее поставленном коде может перевесить преимущества удобства обслуживания в результате рефакторинга кода.

Примечание.

В этом правиле могут отображаться предупреждения о ложноположительных срабатываниях, если применяются все указанные ниже действия.

  • Вы используете Visual Studio 2022 версии 17.5 или более поздней версии с более старой версией пакета SDK для .NET, то есть .NET 6 или более ранней версии.
  • Вы используете анализаторы из пакета SDK для .NET 6 или более старой версии пакетов анализатора, например Microsoft.CodeAnalysis.FxCopAnalyzers.

Ложные срабатывания обусловлены критическим изменением компилятора C#. Рассмотрите возможность использования более нового анализатора, содержащего исправление для предупреждений ложноположительных срабатываний. Обновление до Microsoft.CodeAnalysis.NetAnalyzers версии 7.0.0-preview1.22464.1 или более поздней версии или использование анализаторов из пакета SDK для .NET 7.

Отключение предупреждений

Если вы просто хотите отключить одно нарушение, добавьте директивы препроцессора в исходный файл, чтобы отключить и повторно включить правило.

#pragma warning disable CA1502
// The code that's violating the rule is on this line.
#pragma warning restore CA1502

Чтобы отключить правило для файла, папки или проекта, задайте его серьезность none в файле конфигурации.

[*.{cs,vb}]
dotnet_diagnostic.CA1502.severity = none

Дополнительные сведения см. в разделе Практическое руководство. Скрытие предупреждений анализа кода.

Настройка порогового значения

Пороговое значение, с помощью которого это правило запускается, и типы символов для анализа. Допустимые типы символов:

  • Assembly
  • Namespace
  • Type
  • Method
  • Field
  • Event
  • Property
  1. Создайте текстовый файл с именем CodeMetricsConfig.txt.

  2. Добавьте требуемое пороговое значение в текстовый файл в следующем формате:

    CA1502: 10
    

    В этом примере правило настроено на срабатывание, если цикломатическая сложность метода превышает 10.

    CA1502(Type): 4
    

    В этом примере правило настроено на срабатывание, если цикломатическая сложность типа превышает 4. В этом файле конфигурации правило продолжит сообщать о методах с цикломатической сложностью, превышающей значение по умолчанию (25).

  3. В файле проекта пометьте действие сборки файла конфигурации как AdditionalFiles. Например:

    <ItemGroup>
      <AdditionalFiles Include="CodeMetricsConfig.txt" />
    </ItemGroup>
    

Как вычисляется цикломатическая сложность

Цикломатическая сложность вычисляется путем добавления 1 к следующим значениям:

  • Число ветвей (например if, , whileи do).
  • Число case операторов в объекте switch.

Примеры

В следующих примерах показаны методы с разной цикломатической сложностью.

Цикломатическая сложность 1

public void Method()
{
    Console.WriteLine("Hello World!");
}
Public Sub Method()
    Console.WriteLine("Hello World!")
End Sub

Цикломатическая сложность 2

void Method(bool condition)
{
    if (condition)
    {
        Console.WriteLine("Hello World!");
    }
}
Public Sub Method(ByVal condition As Boolean)
    If (condition) Then
        Console.WriteLine("Hello World!")
    End If
End Sub

Цикломатическая сложность 3

public void Method(bool condition1, bool condition2)
{
    if (condition1 || condition2)
    {
        Console.WriteLine("Hello World!");
    }
}
Public Sub Method(ByVal condition1 As Boolean, ByVal condition2 As Boolean)
    If (condition1 OrElse condition2) Then
        Console.WriteLine("Hello World!")
    End If
End Sub

Цикломатическая сложность 8

public void Method(DayOfWeek day)
{
    switch (day)
    {
        case DayOfWeek.Monday:
            Console.WriteLine("Today is Monday!");
            break;
        case DayOfWeek.Tuesday:
            Console.WriteLine("Today is Tuesday!");
            break;
        case DayOfWeek.Wednesday:
            Console.WriteLine("Today is Wednesday!");
            break;
        case DayOfWeek.Thursday:
            Console.WriteLine("Today is Thursday!");
            break;
        case DayOfWeek.Friday:
            Console.WriteLine("Today is Friday!");
            break;
        case DayOfWeek.Saturday:
            Console.WriteLine("Today is Saturday!");
            break;
        case DayOfWeek.Sunday:
            Console.WriteLine("Today is Sunday!");
            break;
    }
}
Public Sub Method(ByVal day As DayOfWeek)
    Select Case day
        Case DayOfWeek.Monday
            Console.WriteLine("Today is Monday!")
        Case DayOfWeek.Tuesday
            Console.WriteLine("Today is Tuesday!")
        Case DayOfWeek.Wednesday
            Console.WriteLine("Today is Wednesday!")
        Case DayOfWeek.Thursday
            Console.WriteLine("Today is Thursday!")
        Case DayOfWeek.Friday
            Console.WriteLine("Today is Friday!")
        Case DayOfWeek.Saturday
            Console.WriteLine("Today is Saturday!")
        Case DayOfWeek.Sunday
            Console.WriteLine("Today is Sunday!")
    End Select
End Sub

CA1501: избегайте излишнего наследования

См. также