Expression Tree Practice: C# Conditional Statements
[TOC]
Conditional Statements
C# provides the following types of conditional statements:
Statement | Description |
---|---|
if | An if statement consists of a boolean expression followed by one or more statements. |
if...else | An if statement can be followed by an optional else statement, which executes when the boolean expression is false. |
Nested if statements | You can use another if or else if statement within an if or else if statement. |
switch statement | A switch statement allows testing a variable against multiple values. |
Nested switch statements | You can use another switch statement within a switch statement. |
Of course, there are also ??
, ?:
, and other conditionals, which will be detailed in practice below.
if
The if statement is expressed using IfThen(Expression test, Expression ifTrue);
Expression test
represents the expression used for judgment, and Expression ifTrue
represents the expression tree that executes when the result is true.
Example
int a = 10;
int b = 10;
if (a == b)
{
Console.WriteLine("a == b is true; the statement is executed");
}
Console.ReadKey();</code></pre>
Implementing this using expression trees is as follows:
ParameterExpression a = Expression.Variable(typeof(int), "a");
ParameterExpression b = Expression.Variable(typeof(int), "b");
MethodCallExpression call = Expression.Call(
null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
Expression.Constant("a == b is true; the expression tree is executed"));
ConditionalExpression _if = Expression.IfThen(Expression.Equal(a, b), call);
Expression<Action<int, int>> lambda = Expression.Lambda<Action<int, int>>(_if, a, b);
lambda.Compile()(10, 10);
Console.ReadKey();</code></pre>
The generated expression tree is as follows:
.Lambda #Lambda1<System.Action`2[System.Int32,System.Int32]>(
System.Int32 $a,
System.Int32 $b) {
.If ($a == $b) {
.Call System.Console.WriteLine("a == b is true; the expression tree is executed")
} .Else {
.Default(System.Void)
}
}
if...else
The if...else is represented using the following expression tree:
ConditionalExpression IfThenElse(Expression test, Expression ifTrue, Expression ifFalse);
Example code is as follows:
int a = 10;
int b = 11;
if (a == b)
{
Console.WriteLine("a == b is true; this statement is executed");
}
else
{
Console.WriteLine("a == b is false; this statement is executed");
}
Console.ReadKey();</code></pre>
Implementing this using expression trees is as follows:
ParameterExpression a = Expression.Variable(typeof(int), "a");
ParameterExpression b = Expression.Variable(typeof(int), "b");
MethodCallExpression call1 = Expression.Call(
null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
Expression.Constant("a == b is true; this expression tree is executed"));
MethodCallExpression call2 = Expression.Call(
null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
Expression.Constant("a == b is false; this expression tree is executed"));
ConditionalExpression _if = Expression.IfThenElse(Expression.Equal(a, b), call1, call2);
Expression<Action<int, int>> lambda = Expression.Lambda<Action<int, int>>(_if, a, b);
lambda.Compile()(10, 11);
Console.ReadKey();</code></pre>
The generated expression tree is as follows:
.Lambda #Lambda1<System.Action`2[System.Int32,System.Int32]>(
System.Int32 $a,
System.Int32 $b) {
.If ($a == $b) {
.Call System.Console.WriteLine("a == b is true; this expression tree is executed")
} .Else {
.Call System.Console.WriteLine("a == b is false; this expression tree is executed")
}
}
switch
Example code is as follows:
int a = 2;
switch (a)
{
case 1: Console.WriteLine("a == 1"); break;
case 2: Console.WriteLine("a == 2"); break;
default: Console.WriteLine("a != 1 && a == 2");
}
Console.ReadKey();</code></pre>
Each case is represented using the SwitchCase type and is generated using Expression.SwitchCase.
Expression.Switch is used to construct a switch expression tree.
There are many overloads for Expression.Switch, but the common form is:
SwitchExpression Switch(Expression switchValue, Expression defaultBody, params SwitchCase[] cases);
switchValue
represents the input parameter;
defaultBody
represents the expression executed for default;
cases
represents multiple case clauses.
The above code can be rewritten using expression trees as follows:
ParameterExpression a = Expression.Parameter(typeof(int), "a");
MethodCallExpression _default = Expression.Call(
null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
Expression.Constant("a != 1 && a == 2"));
SwitchCase case1 = Expression.SwitchCase(
Expression.Call(null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
Expression.Constant("a == 1")),
new ConstantExpression[] { Expression.Constant(1) }
);
SwitchCase case2 = Expression.SwitchCase(
Expression.Call(null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
Expression.Constant("a == 2")),
new ConstantExpression[] { Expression.Constant(2) }
);
SwitchExpression _switch = Expression.Switch(a, _default, new SwitchCase[] { case1, case2 });
Expression<Action<int>> lambda = Expression.Lambda<Action<int>>(_switch, a);
lambda.Compile()(1);
Console.ReadKey();</code></pre>
The generated expression tree is as follows:
.Lambda #Lambda1<System.Action`1[System.Int32]>(System.Int32 $a) {
.Switch ($a) {
.Case (1):
.Call System.Console.WriteLine("a == 1")
.Case (2):
.Call System.Console.WriteLine("a == 2")
.Default:
.Call System.Console.WriteLine("a != 1 && a == 2")
}
}
Interestingly, there is no break, yet the expression tree is normal and runs without issues.
?? and ?:
??
represents the null-coalescing operator, for example, a ?? b
, which returns a if a is not null; otherwise, it returns b;
The common definition is:
BinaryExpression Coalesce(Expression left, Expression right)
This will not be elaborated further.
?:
is the ternary operator, for example, a > b ? a : b
.
The common definition is:
ConditionalExpression Condition(Expression test, Expression ifTrue, Expression ifFalse)
Refer to the previously mentioned if...else expression tree; this will not be elaborated further.
文章评论