计算switch语句中的个案数

时间:2012-08-30 19:14:11

标签: c# switch-statement counting

我想要一个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

(在计数中是否包含默认情况并不重要。此外,CaseCounter的参数不需要是字符串;任何可以某种方式用于表示方法的类型会做的。)

那么,您将如何实施CaseCounter?它甚至可能吗?

--- ADDENDUM(编辑)---

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

我正在维护一个代码库,其中包含很多打开枚举的方法。这些方法分布在各个类别中;这会在枚举枚举时使生活变得困难(例如,当您添加新的Painter时)。为了使维护更容易,我已经编写了以下形式的单元测试:

// 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枚举的所有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);
}

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

4 个答案:

答案 0 :(得分:5)

应该可以使用the Roslyn CTP - Microsoft的编译器即服务预发布产品。它具有API,可让您检查C#代码并将其表示为指令树。不幸的是,它是一个CTP,对你来说可能是也可能不是问题 - 只要记住它是预发布软件,如果你试图使用它。

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

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

另请参阅this related question

答案 1 :(得分:4)

这不能通过Reflection完成,但可以通过Roslyn CTP完成。 Roslyn提供了分析源代码本身所需的工具,并确定了有关它的信息。您可以在此代码中遍历树以查找包含switch语句的方法,并计算单个案例。

答案 2 :(得分:3)

在不知道你为什么要这样做的情况下,很难知道这对你来说是否是一种可接受的方法。

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

现在,如果您需要在运行时在应用程序中运行此功能,则此方法将无效。

答案 3 :(得分:0)

在视觉工作室中根据您的案例词进行搜索搜索,这足以让您进行重构