分享方式:


CA1502:避免造成過度複雜的方法

屬性
規則識別碼 CA1502
標題 避免造成過度複雜的方法
類別 可維護性
修正程式是中斷或非中斷 不中斷
默認閾值 25
預設在 .NET 8 中啟用 No

原因

方法具有過多的旋風複雜度。

檔案描述

旋形複雜度 會透過 方法測量線性獨立路徑的數目,而此方法是由條件式分支的數目和複雜度所決定。 低旋式複雜度通常表示容易瞭解、測試和維護的方法。 旋式複雜度是從 方法的控制流程圖計算而來,並提供如下:

旋式複雜度 = 邊緣數目 - 節點數目 + 1

節點代表邏輯分支點,邊緣代表節點之間的線條。

當方法的旋式複雜度超過 25 時,規則會報告違規。 不過,您可以 設定閾值 ,同時指定規則應該分析的其他符號類型。

您可以在測量Managed程式碼的複雜度, 深入瞭解程式代碼計量。

如何修正違規

若要修正此規則的違規問題,請重構 方法來降低其旋式複雜性。

隱藏警告的時機

如果無法輕易降低複雜度,而且方法很容易理解、測試及維護,則隱藏此規則的警告是安全的。 特別是,包含大型 switchSelect 在 Visual Basic 中) 語句的方法是排除的候選專案。 在開發週期後期破壞程式代碼基底不穩定,或在先前出貨的程式代碼中引入非預期的運行時間行為變更,可能會超過重構程式代碼的可維護性優點。

注意

如果適用下列所有專案,您可能會看到來自此規則的誤判警告:

  • 您使用 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:避免在物件間過度繼承

另請參閱