为什么带有 `switch` 的代码的圈复杂度高于带有 'if-else' 的代码

Why cyclomatic complexity of code with `switch` higher than that of with 'if-else'

我有两个示例函数 TestComplexityIfTestComplexitySwitch。 VisualStudio-2017 'Calculate Code Metrics' 工具报告带有 switch 语句的函数的圈复杂度为 10,而带有 if-else 的函数的圈复杂度为 7。我想知道 TestComplexitySwitch() 的复杂度是如何计算的。

private static void TestComplexityIf(String arg)
{
    if (arg == "a")
    { }
    else if (arg == "b")
    { }
    else if (arg == "c")
    { }
    else if (arg == "d")
    { }
    else if (arg == "d")
    { }
    else if (arg == "f")
    { }
    else if (arg == "g")
    { }
}

private static void TestComplexitySwitch(String arg)
{
    switch (arg)
    {
        case "a":
            break;
        case "b":
            break;
        case "c":
            break;
        case "d":
            break;
        case "e":
            break;
        case "f":
            break;
        case "g":
            break;
    }
}

此外,如果我评论最后一个案例,复杂度突然变为 6。

private static void TestComplexitySwitch(String arg)
{
    switch (arg)
    {
        case "a":
            break;
        case "b":
            break;
        case "c":
            break;
        case "d":
            break;
        case "e":
            break;
        case "f":
            break;
        //case "g":
            //break;
    }
}

Visual Studio 圈复杂度 (CC) 工具从 IL 代码计算值,因此受编译器详细信息的约束。

在这里您遇到了性能编译器的细节问题:当字符串上的 switch 严格超过 6 cases 时,编译器创建一个散列 table 用于快速字符串搜索。此散列 table 不会出现在 C# 代码中,而只会出现在 IL 代码中。 IL 代码变得更加复杂以处理此散列 table,并且您会得到意外的 CC 值。 this link from Michael Randall.

很好地说明了这种情况

或者,您可以使用 NDepend 工具 compute the CC from C# source code, visualize CC values in a colored treemap and run some rules to forbid too complex methods

(免责声明我为 NDepend 工作)