CA1502:避免造成過度複雜的方法
屬性 | 值 |
---|---|
規則識別碼 | CA1502 |
職稱 | 避免造成過度複雜的方法 |
類別 | 可維護性 |
修正程式是中斷或非中斷 | 不中斷 |
默認閾值 | 25 |
預設在 .NET 9 中啟用 | No |
原因
方法具有過多的旋風複雜度。
檔案描述
旋形複雜度 會透過 方法測量線性獨立路徑的數目,而此方法是由條件式分支的數目和複雜度所決定。 低旋式複雜度通常表示容易瞭解、測試和維護的方法。 旋式複雜度是從 方法的控制流程圖計算而來,並提供如下:
旋式複雜度 = 邊緣數目 - 節點數目 + 1
節點代表邏輯分支點,邊緣代表節點之間的線條。
當方法的旋式複雜度超過 25 時,規則會報告違規。 不過,您可以 設定閾值 ,同時指定規則應該分析的其他符號類型。
您可以在測量Managed程式碼的複雜度, 深入瞭解程式代碼計量。
如何修正違規
若要修正此規則的違規問題,請重構 方法來降低其旋式複雜性。
隱藏警告的時機
如果無法輕易降低複雜度,而且方法很容易理解、測試及維護,則隱藏此規則的警告是安全的。 特別是,包含大型 switch
(Select
在 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
建立名為 CodeMetricsConfig.txt 的文字檔。
以下列格式將所需的臨界值新增至文字檔:
CA1502: 10
在此範例中,當方法的旋式複雜度大於 10 時,規則會設定為引發。
CA1502(Type): 4
在此範例中,當類型的旋式複雜度大於 4 時,規則會設定為引發。 使用此組態檔時,規則會繼續報告具有大於預設值 (25) 的旋式複雜度的方法。
在項目檔中,將組態檔的建置動作標示為 AdditionalFiles。 例如:
<ItemGroup> <AdditionalFiles Include="CodeMetricsConfig.txt" /> </ItemGroup>
如何計算旋式複雜度
循環複雜度是藉由將 1 新增至下列項目來計算:
- 分支數目(例如
if
、while
和do
)。 - 中的
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