CA1502:避免過度複雜
型別名稱 |
AvoidExcessiveComplexity |
CheckId |
CA1502 |
分類 |
Microsoft.Maintainability |
中斷變更 |
中斷 |
原因
方法的循環複雜度超過一般情況。
規則描述
「循環複雜度」(Cyclomatic Complexity) 會測量整個方法中線性獨立路徑的數目,此數目是由條件分支的數目與複雜度決定。 較低的循環複雜度通常表示方法是易於了解、測試和維護。 循環複雜度是從方法的控制流程圖計算得出,它的公式如下:
循環複雜度 = 邊緣數目 - 節點數目 + 1
其中 node 表示邏輯分支點,edge 則表示 node 之間的線。
當循環複雜度超過 25 時,此規則會報告違規情形。
您可以進一步了解程式碼度量。請參考 測量 Managed 程式碼的複雜度和維護性。
如何修正違規
若要修正此規則的違規情形,請重構方法以降低循環複雜度。
隱藏警告的時機
如果無法輕易降低複雜度,而且方法也易於了解、測試和維護,則您可以放心地隱藏這項規則的警告。 包含大型 switch (在 Visual Basic 中為 Select) 陳述式的方法尤其可以列為可排除的候選項目。 在開發週期晚期變動程式碼基底 (Code Base),或是在先前送出之程式碼的執行階段行為中引入未預期的變更,這類的風險會比重構程式碼在維護方面所帶來的優點更加重要。
循環複雜度的計算方式
循環複雜度是藉由在下列各項中加 1 來計算:
分支數目 (例如 if、while 和 do)
switch 中的 case 陳述式數目
下列範例顯示具有各種循環複雜度的方法。
範例
循環複雜度為 1
Public Sub Method()
Console.WriteLine("Hello World!")
End Sub
public void Method()
{
Console.WriteLine("Hello World!");
}
void Method()
{
Console::WriteLine("Hello World!");
}
循環複雜度為 2
Public Sub Method(ByVal condition As Boolean)
If (condition) Then
Console.WriteLine("Hello World!")
End If
End Sub
void Method(bool condition)
{
if (condition)
{
Console.WriteLine("Hello World!");
}
}
void Method(bool condition)
{
if (condition)
{
Console::WriteLine("Hello World!");
}
}
循環複雜度為 3
Public Sub Method(ByVal condition1 As Boolean, ByVal condition2 As Boolean)
If (condition1 OrElse condition2) Then
Console.WriteLine("Hello World!")
End If
End Sub
public void Method(bool condition1, bool condition2)
{
if (condition1 || condition2)
{
Console.WriteLine("Hello World!");
}
}
void Method(bool condition1, bool condition2)
{
if (condition1 || condition2)
{
Console::WriteLine("Hello World!");
}
}
循環複雜度為 8
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
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;
}
}
}
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;
}
}