Jeroen van Langen
Jeroen van Langen

Reputation: 22038

Expression.Switch() struggling on case implementation

I'm trying to implement the Expression.Switch() to create a switch statement within my expressions. I'm struggling with some issues.

I've created a small example that raises the exception. The switch uses a string to switch the cases and within that case it will assign a variable.

Here is some code that will raise the exception:

// an int variable
var var1 = Expression.Parameter(typeof(int));
// a string variable
var var2 = Expression.Parameter(typeof(string));

var cases = new[] 
{ 
    // the first case 'SwitchCaseValue1' should write the int value 1 into variable var1
    Expression.SwitchCase(Expression.Assign(var1, Expression.Constant(1)), Expression.Constant("SwitchCaseValue1")),
    // the second case 'SwitchCaseValue2' should write the string value 'Example' into variable var2 
    Expression.SwitchCase(Expression.Assign(var2, Expression.Constant("Example")), Expression.Constant("SwitchCaseValue2"))
};

Expression.Switch(Expression.Constant("SwitchValue"), cases);

This will raise this excepion: All case bodies and the default body must have the same type.

I think this refers to the Assign returning for case 1 an int and for case 2 a string. How can i return nothing?


If I change the var2 to type int:

// an int variable
var var1 = Expression.Parameter(typeof(int));
// a string variable
var var2 = Expression.Parameter(typeof(int));

var cases = new[] 
{ 
    // the first case 'SwitchCaseValue1' should write the int value 1 into variable var1
    Expression.SwitchCase(Expression.Assign(var1, Expression.Constant(1)), Expression.Constant("SwitchCaseValue1")),
    // the second case 'SwitchCaseValue2' should write the string value 'Example' into variable var2 
    Expression.SwitchCase(Expression.Assign(var2, Expression.Constant(2)), Expression.Constant("SwitchCaseValue2"))
};

Expression.Switch(Expression.Constant("SwitchValue"), cases);

It raises exception: Default body must be supplied if case bodies are not System.Void.

So i changed: the last line to Expression.Switch(Expression.Constant("SwitchValue"), Expression.Constant(0), cases);

This will compile. but is not what I'm looking for...


Is there another way to fix this first solution without implementing extra code to return the same type?

I don't like solutions like selecting a meaningless return value, like:

// an int variable
var var1 = Expression.Parameter(typeof(int));
// a string variable
var var2 = Expression.Parameter(typeof(string));

var cases = new[] 
{ 
    // the first case 'SwitchCaseValue1' should write the int value 1 into variable var1
    Expression.SwitchCase(
        Expression.Block( 
            Expression.Assign(var1, Expression.Constant(1)), 
            // return a boolean
            Expression.Constant(true)), 
        Expression.Constant("SwitchCaseValue1")),
    // the second case 'SwitchCaseValue2' should write the string value 'Example' into variable var2 
    Expression.SwitchCase(
        Expression.Block( 
            Expression.Assign(var2, Expression.Constant("Example")), 
            // return a boolean
            Expression.Constant(true)), 
        Expression.Constant("SwitchCaseValue2"))
};


Expression.Switch(Expression.Constant("SwitchValue"), Expression.Constant(false), cases);

I understand the logic of Expressions and returning a value. But is there a way to avoid implementing meaningless code?

Upvotes: 4

Views: 776

Answers (1)

Jeroen van Langen
Jeroen van Langen

Reputation: 22038

I found the answer myself

The Expression.Switch() has an overload Switch(Type type, Expression switchValue, Expression defaultBody, MethodInfo comparison, IEnumerable<SwitchCase> cases);

When using this overload and passing typeof(void) into the parameter type, it will accept it.

msdn: "All SwitchCase objects in a SwitchExpression object must have the same type, unless the SwitchExpression has the type void." I didn't make the connection between the SwitchExpression type and an overload containing a type parameter.

This will do the job:

// an int variable
var var1 = Expression.Parameter(typeof(int));
// a string variable
var var2 = Expression.Parameter(typeof(string));

var cases = new[] 
{ 
    // the first case 'SwitchCaseValue1' should write the int value 1 into variable var1
    Expression.SwitchCase(
            Expression.Assign(var1, Expression.Constant(1)), 
            Expression.Constant("SwitchCaseValue1")),
    // the second case 'SwitchCaseValue2' should write the string value 'Example' into variable var2 
    Expression.SwitchCase(
            Expression.Assign(var2, Expression.Constant("Example")), 
            Expression.Constant("SwitchCaseValue2"))
};

Expression.Switch(typeof(void), Expression.Constant("SwitchValue"), null, null, cases);

Upvotes: 6

Related Questions