C# 计算switch语句中的案例数
我想要一个C#方法,计算一个开关站的案例数量。(我们称之为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:
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查看它们……我就是这么做的。在我的测试中,单个caseswitch
语句编译成一个简单的条件分支。四格switch
语句编译为实际的ILswitch
指令。因此@driis使用GetMethodBody
的答案并不总是能找到这些。(代码和IL at)