4

我想要一个 C# 方法来计算 switch 语句中的案例数。(我们称之为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

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

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

--- 附录(编辑) ---

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

我正在维护一个代码库,其中包含许多打开枚举的方法。这些方法分布在各个类中;当枚举扩展时(例如,当您添加一个新的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的所有 5 个可能值。)Painter

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

[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

4 回答 4

5

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

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

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

另外,请参阅此相关问题

于 2012-08-30T19:18:20.283 回答
4

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

于 2012-08-30T19:17:43.920 回答
3

在不知道您为什么这样做的情况下,很难知道这是否是您可以接受的方法。

Since these C# files are basically just text files on your computer, you could create a separate application that loops through all the files. It would need to recognize methods, count the number of occurrences of case words (that aren't comments), and report the results.

Now, if you need this functionality to run at runtime, within your app, then this approach won't work.

于 2012-08-30T19:31:55.673 回答
0

make a find search in visual studio on your case word it is enough to make your refactoring

于 2012-08-30T19:32:05.263 回答