CA1502:メソッドの実装を複雑にしすぎないでください

プロパティ
ルール ID CA1502
Title メソッドの実装を複雑にしすぎないでください
[カテゴリ] 保守容易性
修正が中断ありか中断なしか なし
既定のしきい値 25
.NET 8 では既定で有効 いいえ

原因

メソッドに、過剰なサイクロマティック複雑度があります。

規則の説明

サイクロマティック複雑度は、線形独立のメソッド経路数を示す尺度で、条件分岐の数と複雑さによって決まります。 サイクロマティック複雑度が低いとは、一般に、そのメソッドが理解しやすく、テストおよび保守が容易であることを示しています。 サイクロマティック複雑度は、メソッドの制御フロー グラフから計算され、次のように算出されます。

サイクロマティック複雑度 = エッジの数 - ノードの数 + 1

ノードはロジックの分岐点を表し、エッジはノード間の線を表します。

この規則は、メソッドのサイクロマティック複雑度が 25 を超える場合に違反を報告します。 ただし、しきい値を構成したり、ルールで分析する他の種類のシンボルを指定したりすることもできます。

コード メトリックの詳細については、マネージ コードの複雑さの測定に関するページを参照してください。

違反の修正方法

この規則違反を修正するには、メソッドをリファクタリングして、サイクロマティック複雑度を下げます。

どのようなときに警告を抑制するか

複雑さを簡単に軽減できない場合、またメソッドが理解しやすく、テストおよび保守が容易に行える場合は、この規則による警告を抑制しても問題ありません。 特に、大規模な switch (Visual Basic では Select) ステートメントを含むメソッドは、除外の候補です。 開発サイクルの後半でコードベースの安定性を損なうリスクがある、または以前に出荷されたコードで実行時の動作に予期しない変更が発生してしまうリスクがあるならば、コードをリファクタリングすることによって保守容易性を向上させるよりも、それらのリスクを避ける方が良い場合があります。

Note

次のすべてに該当する場合、このルールから擬陽性の警告が表示される場合があります。

  • Visual Studio 2022 バージョン 17.5 以降を NET SDK の古いバージョン (.NET 6 以前) で使用している場合。
  • .NET 6 SDK またはそれ以前のバージョンのアナライザー パッケージ (Microsoft.CodeAnalysis.FxCopAnalyzers など) のアナライザーを使用している場合。

擬陽性は、C# コンパイラの破壊的変更が原因です。 擬陽性警告の修正プログラムを含む新しいアナライザーの使用を検討してください。 Microsoft.CodeAnalysis.NetAnalyzers バージョン 7.0.0-preview1.22464.1 以降にアップグレードするか、.NET 7 SDK のアナライザーを使用します。

警告を抑制する

単一の違反を抑制するだけの場合は、ソース ファイルにプリプロセッサ ディレクティブを追加して無効にしてから、規則をもう一度有効にします。

#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 を追加することによって計算されます。

  • 分岐の数 (ifwhiledo など)。
  • switch における case ステートメントの数。

次の例は、さまざまなサイクロマティック複雑度を持つメソッドを示しています。

サイクロマティック複雑度 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:継承を使用しすぎないでください

関連項目