Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Counting the number of cases in a switch statement

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? Is it even possible?

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

(In this example, IsModernAllCases is just a variation of 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.

like image 602
user181813 Avatar asked Dec 16 '22 20:12

user181813


1 Answers

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 Cecil Mono project, which has some API's for inspecting IL.

You could also MethodInfo.GetMethodBody to get the raw IL bytes and then parse those bytes yourself, but it does require some work to do that.

Also, see this related question.

like image 153
driis Avatar answered Dec 28 '22 23:12

driis