Редагувати

Поділитися через


CA1502: Avoid excessive complexity

Property Value
Rule ID CA1502
Title Avoid excessive complexity
Category Maintainability
Fix is breaking or non-breaking Non-breaking
Default threshold 25
Enabled by default in .NET 9 No

Cause

A method has an excessive cyclomatic complexity.

Rule description

Cyclomatic complexity measures the number of linearly independent paths through the method, which is determined by the number and complexity of conditional branches. A low cyclomatic complexity generally indicates a method that is easy to understand, test, and maintain. The cyclomatic complexity is calculated from a control flow graph of the method and is given as follows:

cyclomatic complexity = the number of edges - the number of nodes + 1

A node represents a logic branch point and an edge represents a line between nodes.

The rule reports a violation when the cyclomatic complexity of a method is more than 25. However, you can configure the threshold and also specify other kinds of symbols that the rule should analyze.

You can learn more about code metrics at Measure complexity of managed code.

How to fix violations

To fix a violation of this rule, refactor the method to reduce its cyclomatic complexity.

When to suppress warnings

It is safe to suppress a warning from this rule if the complexity cannot easily be reduced and the method is easy to understand, test, and maintain. In particular, a method that contains a large switch (Select in Visual Basic) statement is a candidate for exclusion. The risk of destabilizing the code base late in the development cycle or introducing an unexpected change in run-time behavior in previously shipped code might outweigh the maintainability benefits of refactoring the code.

Note

You might see false positive warnings from this rule if all of the following apply:

  • You're using Visual Studio 2022 version 17.5 or later with an older version of the .NET SDK, that is, .NET 6 or earlier.
  • You're using the analyzers from the .NET 6 SDK or an older version of the analyzer packages, such as Microsoft.CodeAnalysis.FxCopAnalyzers.

The false positives are due to a breaking change in the C# compiler. Consider using a newer analyzer that contains the fix for the false positive warnings. Upgrade to Microsoft.CodeAnalysis.NetAnalyzers version 7.0.0-preview1.22464.1 or newer or use the analyzers from the .NET 7 SDK.

Suppress a warning

If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.

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

To disable the rule for a file, folder, or project, set its severity to none in the configuration file.

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

For more information, see How to suppress code analysis warnings.

Configure threshold

You can configure the threshold at which this rule fires and the kinds of symbols to analyze. The allowable symbol kinds are:

  • Assembly
  • Namespace
  • Type
  • Method
  • Field
  • Event
  • Property
  1. Create a text file named CodeMetricsConfig.txt.

  2. Add the desired threshold to the text file in the following format:

    CA1502: 10
    

    In this example, the rule is configured to fire when a method's cyclomatic complexity is greater than 10.

    CA1502(Type): 4
    

    In this example, the rule is configured to fire when a type's cyclomatic complexity is greater than 4. With this configuration file, the rule would continue to report methods with a cyclomatic complexity greater than the default (25).

  3. In the project file, mark the build action of the configuration file as AdditionalFiles. For example:

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

How cyclomatic complexity is calculated

The cyclomatic complexity is calculated by adding 1 to the following:

  • The number of branches (such as if, while, and do).
  • The number of case statements in a switch.

Examples

The following examples show methods that have varying cyclomatic complexities.

Cyclomatic complexity of 1

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

Cyclomatic complexity of 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

Cyclomatic complexity of 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

Cyclomatic complexity of 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: Avoid excessive inheritance

See also