Contar el número de casos en una declaración de cambio

I would like to have a C# method which counts the number of cases in a switch statment. (Let's call it CaseCounter). For example, let's say you have this enum and these two methods:

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;
     }
}

Now the following equalities should hold:

CaseCounter("GetYearOfBirth") == 5
CaseCounter("IsModern") == 2

(It is not important whether or not you include the default case in the count. Also, the parameter to CaseCounter doesn't need to be a string; any type which can somehow be used to represent a method will do.)

So, how would you go about implementing CaseCounter? ¿Es siquiera posible?

--- ADDENDUM (EDIT) ---

Here's a bit of background info in case you're wondering why I asked this question.

I'm maintaining a code base which contains a lot of methods that switch on enums. The methods are spread across various classes; this makes life difficult when an enum is extended (for example, when you add a new Painter). To make maintenance a little bit easier, I have written some unit tests of the following form:

// 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);
}

(En este ejemplo, IsModernAllCases es solo una variación de IsModern which refers explicitly to all 5 possible values of the Painter enum.)

This test is better than nothing, but it's clumsy. It would be a little less clumsy if you could write something like this:

[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);
}

In this scenario, at least you don't have to modify the unit test when you extend the enum.

preguntado el 30 de agosto de 12 a las 20:08

This smells like bad code. -

If you need a computer to tell you how many case statements you have, you have too many case statements. -

@NathanKoop I agree with you completely... I'm asking this question because I'm maintaining a code base where switch statements abound. Refactoring all the switch statements away is not really an option. -

so it is not at runtime that you want to count switch, parsing cs file and detect number of switch is enough -

@HassanBoutougha Yes, you're right. -

4 Respuestas

It should be possible to do with the Roslyn CTP - Microsoft's compiler-as-a-service pre-release product. It has API's to let you inspect C# code and represent it as a tree of instructions. Unfortunately, it is a CTP, which may or may not be a problem for you - just remember it is pre-release software if you try to use it.

If you can't use Roslyn, I think the only way would be to inspect the generated IL. A daunting task, to say the least. I haven't got any sample code for that, but if you want to try it - I would start by looking at the Cecilio Mono project, which has some API's for inspecting IL.

También podrías MethodInfo.GetMethodBody to get the raw IL bytes and then parse those bytes yourself, but it does require some work to do that.

Consulte también la esta pregunta relacionada.

contestado el 23 de mayo de 17 a las 13:05

Just out of curiosity: are the C# switch statements guaranteed to be compiled to the IL switch, or does the compiler have the option of using a simple conditional if the switch set is small? - clinton perforar

@clintp, I suspect if y switch might look the same in IL, though I am not sure. You could try compiling two methods and looking at them with ILSpy... - dris

I just did. And in my test, a single-case switch statement compiles down to a simple conditional branch. A four case switch statements compiles down to an actual IL switch instruction. So @driis's answer of using GetMethodBody won't always work to find these. (Code and IL at pastebin.com/97s4siKN ) - clinton perforar

This can't be done via Reflection, but could be done via the Roslyn CTP. Roslyn provides the tooling required to analyze the source code itself, and determine information about it. You could walk the trees in this code to find the methods containing switch statements, and make a count of individual cases.

Respondido 30 ago 12, 20:08

Without knowing why you are doing this, it's tough to know if this will be an acceptable approach for you.

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.

Respondido 30 ago 12, 20:08

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

Respondido 30 ago 12, 20:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.