Search code examples
c#switch-statementexpressionexpression-trees

How to build a ranged switch case expression at runtime?


I am building a Switch expression to match ranges of integers at runtime. Currently I am able to compile and run the equivalent of the following using Expression.SwitchCase:

switch(value)
{
    case 1:
    case 2:
        Console.WriteLine("1 or 2");
        break;
    case 3:
    case 4:
    case 5:
        Console.WriteLine("3, 4 or 5");
        break;
}

My issue being - I have to create a SwitchCase for every constant in the range I wish to match:

Expression.SwitchCase(body, Expression.Constant(1))

Expression.SwitchCase(body, Expression.Constant(2))

Is there a more concise way to achieve this? Is there a way I can replace that constant expression with an expression that evaluates the switched value against a range?. Performance is also of interest, especially if the range is large.


Solution

  • You can simplify your code with other overload of Expression.SwitchCase

    Just create an array with a test values and convert it to ConstantExpression. Try this example:

    var writeLine = typeof(Console).GetMethod("WriteLine", new[] {typeof(string)});
    
    // body of first block
    var action1 = Expression.Call(writeLine, Expression.Constant("1 or 2"));
    // body of second block
    var action2 = Expression.Call(writeLine, Expression.Constant("3, 4 or 5"));
    
    var value = Expression.Parameter(typeof(int), "value");
    var body = Expression.Switch(value,
        Expression.SwitchCase(
          action1,
          new[] {1, 2}.Select(i => Expression.Constant(i))),
        Expression.SwitchCase(
          action2, 
          new[] {3, 4, 5}.Select(i => Expression.Constant(i)))
    );
    
    var lambda = Expression.Lambda<Action<int>>(body, value);
    var method = lambda.Compile();
    
    method(1); // print "1 or 2"
    method(4); // print "3, 4 or 5"