C# 计算switch语句中的案例数

C# 计算switch语句中的案例数,c#,switch-statement,counting,C#,Switch Statement,Counting,我想要一个C#方法,计算一个开关站的案例数量。(我们称之为CaseCounter)。例如,假设您有这个枚举和这两个方法: enum Painter { Rubens, Rembrandt, Vermeer, Picasso, Kandinsky } int GetYearOfBirth(Painter painter) { switch(painter) { case Painter.Kandinsky:

我想要一个C#方法,计算一个开关站的案例数量。(我们称之为
CaseCounter
)。例如,假设您有这个枚举和这两个方法:

enum Painter  
{  
    Rubens,  
    Rembrandt,  
    Vermeer,
    Picasso,
    Kandinsky
}

int GetYearOfBirth(Painter painter)
{
    switch(painter)
    {
        case Painter.Kandinsky:
            return 1866;    
        case Painter.Picasso:
            return 1881;
        case Painter.Rembrandt:
            return 1606;
        case Painter.Rubens:
            return 1577;
        case Painter.Vermeer:
            return 1632;
        default:
            return 0;
    }
}

bool IsModern(Painter painter)
{
    switch (painter)
    {
        case Painter.Kandinsky:
        case Painter.Picasso:
            return true;
        default:
            return false;
     }
}
现在,以下等式应该成立:

CaseCounter("GetYearOfBirth") == 5
CaseCounter("IsModern") == 2
(是否在计数中包含默认大小写并不重要。此外,
caseconter
的参数不需要是字符串;任何可以用来表示方法的类型都可以。)

那么,您将如何实施
CaseCounter
?有可能吗

---增编(编辑)---

这里有一些背景信息,以防你想知道我为什么问这个问题

我正在维护一个代码库,其中包含许多打开枚举的方法。这些方法分布在不同的类中;当扩展枚举时(例如,当您添加新的
画师时),这会使生活变得困难。为了简化维护,我编写了以下形式的一些单元测试:

// If this test fails please check that the following methods are still OK: 
// MyClass.GetYearOfBirth, MyOtherClass.IsModernAllCases . 
// (There is no guarantee that the above list is up-to-date or complete.)
[Test]
public void PainterCountTest()
{
    int numberOfMembers = Enum.GetValues(typeof(NotificationID)).Length;
    Assert.AreEqual(5, numberOfMembers);
}
(在本例中,
IsModernAllCases
只是
IsModern
的一个变体,它明确地引用了
Painter
enum的所有5个可能值。)

这个测试总比什么都没有好,但它很笨拙。如果你能写这样的东西,那就不会那么笨拙了:

[Test]
public void PainterCountTest()
{
    int numberOfMembers = Enum.GetValues(typeof(NotificationID)).Length;

    int numberOfCases_getYearOfBirth = CaseCounter("MyClass.GetYearOfBirth");
    Assert.AreEqual(numberOfCases_getYearOfBirth, numberOfMembers);

    int numberOfCases_modern = CaseCounter("MyOtherClass.IsModernAllCases");
    Assert.AreEqual(numberOfCases_modern, numberOfMembers);
}

在这种情况下,至少在扩展枚举时不必修改单元测试

这不能通过反射完成,但可以通过。Roslyn提供了分析源代码本身并确定其相关信息所需的工具。您可以遍历此代码中的树,找到包含switch语句的方法,并对个别情况进行计数。

应该可以使用-Microsoft的compiler-as-a-service预发布产品。它有API,让您可以检查C#代码并将其表示为指令树。不幸的是,它是一个CTP,这可能对您来说是个问题,也可能不是问题——只要记住,如果您尝试使用它,它是预发布的软件

如果你不能使用Roslyn,我认为唯一的方法就是检查生成的IL。至少可以说,这是一项艰巨的任务。我没有这方面的任何示例代码,但是如果你想尝试一下,我会先看看Mono项目,它有一些用于检查IL的API

您也可以
MethodInfo.GetMethodBody
获取原始IL字节,然后自己解析这些字节,但这确实需要一些工作来完成


另外,请参见。

如果不知道您为什么这样做,很难知道这是否是您可以接受的方法

由于这些C#文件基本上只是计算机上的文本文件,因此您可以创建一个单独的应用程序,在所有文件中循环。它需要识别方法,统计
大小写
单词(不是注释)的出现次数,并报告结果


现在,如果您需要在运行时在应用程序中运行此功能,那么此方法将不起作用。

在visual studio中对您的案例词进行查找搜索,这足以使您的重构闻起来像是糟糕的代码。如果您需要一台计算机来告诉您有多少案例语句,你的陈述太多了。@NathanKoop我完全同意你的观点。。。我问这个问题是因为我在维护一个代码库,其中有大量switch语句。重构所有switch语句并不是一个真正的选项。所以,在运行时,您不想计算switch的数量,解析cs文件并检测switch的数量enough@HassanBoutougha是的,你说得对。只是出于好奇:C#
开关
语句是否保证编译成IL
开关
,或者如果开关集很小,编译器可以选择使用简单的条件吗?@clintp,我怀疑
if
switch
在IL中可能看起来是一样的,尽管我不确定。您可以尝试编译两个方法,并使用ILSpy查看它们……我就是这么做的。在我的测试中,单个case
switch
语句编译成一个简单的条件分支。四格
switch
语句编译为实际的IL
switch
指令。因此@driis使用
GetMethodBody
的答案并不总是能找到这些。(代码和IL at)