c语言表达式树原理,表达式树练习实践:C# 五类运算符的表达式树表达

表达式树练习实践:C# 运算符

目录

在 C# 中,算术运算符,有以下类型算术运算符

关系运算符

逻辑运算符

位运算符

赋值运算符

其他运算符

这些运算符根据参数的多少,可以分作一元运算符、二元运算符、三元运算符。本文将围绕这些运算符,演示如何使用表达式树进行操作。

对于一元运算符和二元运算符的 Expression 的子类型如下:UnaryExpression; //一元运算表达式

BinaryExpression; //二元运算表达式

一,算术运算符运算符描述+把两个操作数相加

-从第一个操作数中减去第二个操作数

*把两个操作数相乘

/分子除以分母

%取模运算符,整除后的余数

++自增运算符,整数值增加 1

--自减运算符,整数值减少 1

+ 与 Add()

正常代码int a;

int b;

a = 100;

b = 200;

var ab = a + b;

Console.WriteLine(ab);

使用表达式树构建ParameterExpression a = Expression.Parameter(typeof(int), "a");

ParameterExpression b = Expression.Parameter(typeof(int), "b");

// ab = a + b

BinaryExpression ab = Expression.Add(a, b);

// 打印 a + b 的值

MethodCallExpression method = Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }), ab);

Expression lambda = Expression.Lambda(method, a, b);

lambda.Compile()(100, 200);

Console.ReadKey();

如果想复杂一些,使用 块 来执行:ParameterExpression a = Expression.Parameter(typeof(int), "a");

ParameterExpression b = Expression.Parameter(typeof(int), "b");

// 别忘记了赋值

BinaryExpression aa = Expression.Assign(a, Expression.Constant(100, typeof(int)));

BinaryExpression bb = Expression.Assign(b, Expression.Constant(200, typeof(int)));

// ab = a + b

BinaryExpression ab = Expression.Add(a, b);

// 打印 a + b 的值

MethodCallExpression method = Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }), ab);

// 以块的形式执行代码,相当于{ }

// 不需要纠结这里,后面会有详细说明,重点是上面

var call = Expression.Block(new ParameterExpression[] { a, b }, aa, bb, method);

Expressionlambda = Expression.Lambda(call);

lambda.Compile()();

上面两个示例,是使用表达式树计算结果,然后还是使用表达式树打印结果。

前者依赖外界传入参数值,赋予 a、b,后者则全部使用表达式树赋值和运算。

那么,如何通过表达式树执行运算,获取执行结果呢?ParameterExpression a = Expression.Parameter(typeof(int), "a");

ParameterExpression b = Expression.Parameter(typeof(int), "b");

// ab = a + b

BinaryExpression ab = Expression.Add(a, b);

Expression lambda = Expression.Lambda(ab, a, b);

int result = lambda.Compile()(100, 200);

Console.WriteLine(result);

Console.ReadKey();

这些区别在于如何编写 Expression.Lambda()。

另外,使用 AddChecked() 可以检查操作溢出。

- 与 Subtract()

与加法一致,此处不再赘述,SubtractChecked() 可以检查溢出。

a - b ,结果是 100 。ParameterExpression a = Expression.Parameter(typeof(int), "a");

ParameterExpression b = Expression.Parameter(typeof(int), "b");

// ab = a - b

BinaryExpression ab = Expression.Subtract(a, b);

Expression lambda = Expression.Lambda(ab, a, b);

int result = lambda.Compile()(200, 100);

Console.WriteLine(result);

乘除、取模

乘法// ab = a * b

BinaryExpression ab = Expression.Multiply(a, b);

// ab = 20000

除法// ab = a / b

BinaryExpression ab = Expression.Divide(a, b);

// ab = 2

取模(%)ParameterExpression a = Expression.Parameter(typeof(int), "a");

ParameterExpression b = Expression.Parameter(typeof(int), "b");

// ab = a % b

BinaryExpression ab = Expression.Modulo(a, b);

Expression lambda = Expression.Lambda(ab, a, b);

int result = lambda.Compile()(200, 150);

// ab = 50

Console.WriteLine(result);

Console.ReadKey();

自增自减

自增自减有两种模型,一种是 x++ 或 x--,另一种是 ++x 或 --x。

他们都是属于 UnaryExpression 类型。算术运算符表达式树说明x++Expression.PostIncrementAssign()后置

x--Expression.PostDecrementAssign()后置

++xExpression.PreIncrementAssign()前置

--xExpression.PreDecrementAssign()前置

巧记:Post 后置, Pre 前置;Increment 是加,Decrement是减;Assign与赋值有关(后面会说到);

x++ 与 x-- 的使用int a = 10;

int b = 10;

a++;

b--;

Console.WriteLine(a);

Console.WriteLine(b);// int a,b;

ParameterExpression a = Expression.Parameter(typeof(int), "a");

ParameterExpression b = Expression.Parameter(typeof(int), "b");

// a = 10,b = 10;

BinaryExpression setA = Expression.Assign(a, Expression.Constant(10));

BinaryExpression setB = Expression.Assign(b, Expression.Constant(10));

// a++

UnaryExpression aa = Expression.PostIncrementAssign(a);

// b--

UnaryExpression bb = Expression.PostDecrementAssign(b);

//Console.WriteLine(a);

//Console.WriteLine(b);

MethodCallExpression callA = Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }), a);

MethodCallExpression callB = Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }), b);

BlockExpression block = Expression.Block(

new ParameterExpression[] { a, b },

setA,

setB,

aa,

bb,

callA,

callB

);

Expressionlambda = Expression.Lambda(block);

lambda.Compile()();

Console.ReadKey();

如果想把参数从外面传入,设置 a,b// int a,b;

ParameterExpression a = Expression.Variable(typeof(int), "a");

ParameterExpression b = Expression.Variable(typeof(int), "b");

// a++

UnaryExpression aa = Expression.PostIncrementAssign(a);

// b--

UnaryExpression bb = Expression.PostDecrementAssign(b);

//Console.WriteLine(a);

//Console.WriteLine(b);

MethodCallExpression callA = Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }), a);

MethodCallExpression callB = Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }), b);

BlockExpression block = Expression.Block(

aa,

bb,

callA,

callB

);

Expression lambda = Expression.Lambda(block, a, b);

lambda.Compile()(10, 10);

Console.ReadKey();

生成的表达式树如下.Lambda #Lambda1(

System.Int32 $a,

System.Int32 $b) {

.Block() {

$a++;

$b--;

.Call System.Console.WriteLine($a);

.Call System.Console.WriteLine($b)

}

}

为了理解一下 Expression.Block(),可以在这里学习一下(后面会说到 Block())。// int a,b;

ParameterExpression a = Expression.Parameter(typeof(int), "a");

ParameterExpression b = Expression.Parameter(typeof(int), "b");

ParameterExpression c = Expression.Variable(typeof(int), "c");

BinaryExpression SetA = Expression.Assign(a, c);

BinaryExpression SetB = Expression.Assign(b, c);

// a++

UnaryExpression aa = Expression.PostIncrementAssign(a);

// b--

UnaryExpression bb = Expression.PostDecrementAssign(b);

//Console.WriteLine(a);

//Console.WriteLine(b);

MethodCallExpression callA = Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }), a);

MethodCallExpression callB = Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }), b);

BlockExpression block = Expression.Block(

new ParameterExpression[] { a, b },

SetA,

SetB,

aa,

bb,

callA,

callB

);

Expression lambda = Expression.Lambda(block, c);

lambda.Compile()(10);

Console.ReadKey();

为什么这里要多加一个 c 呢?我们来看看生成的表达式树.Lambda #Lambda1(System.Int32 $c) {

.Block(

System.Int32 $a,

System.Int32 $b) {

$a = $c;

$b = $c;

$a++;

$b--;

.Call System.Console.WriteLine($a);

.Call System.Console.WriteLine($b)

}

}

观察一下下面代码生成的表达式树// int a,b;

ParameterExpression a = Expression.Parameter(typeof(int), "a");

ParameterExpression b = Expression.Parameter(typeof(int), "b");

// a++

UnaryExpression aa = Expression.PostIncrementAssign(a);

// b--

UnaryExpression bb = Expression.PostDecrementAssign(b);

//Console.WriteLine(a);

//Console.WriteLine(b);

MethodCallExpression callA = Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }), a);

MethodCallExpression callB = Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }), b);

BlockExpression block = Expression.Block(

new ParameterExpression[] { a, b },

aa,

bb,

callA,

callB

);

Expression lambda = Expression.Lambda(block, a, b);

lambda.Compile()(10, 10);

Console.ReadKey();.Lambda #Lambda1(

System.Int32 $a,

System.Int32 $b) {

.Block(

System.Int32 $a,

System.Int32 $b) {

$a++;

$b--;

.Call System.Console.WriteLine($a);

.Call System.Console.WriteLine($b)

}

}

关于前置的自增自减,按照上面示例编写即可,但是需要注意的是, ++x 和 --x ,是“先运算后增/自减”。

二,关系运算符

==、!=、>、

C# 中的关系运算符如下运算符描述==检查两个操作数的值是否相等,如果相等则条件为真。

!=检查两个操作数的值是否相等,如果不相等则条件为真。

>检查左操作数的值是否大于右操作数的值,如果是则条件为真。

>=检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。

<=检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。

== 表示相等比较,如果是值类型和 string 类型,则比较值是否相同;如果是引用类型,则比较引用的地址是否相等。

其它的关系运算符则是仅比较值类型的大小。

实例代码int a = 21;

int b = 10;

Console.Write("a == b:");

Console.WriteLine(a == b);

Console.Write("a 

Console.WriteLine(a 

Console.Write("a > b :");

Console.WriteLine(a > b);

// 改变 a 和 b 的值

a = 5;

b = 20;

Console.Write("a = b:");

Console.WriteLine(b >= a);

Console.ReadKey();

使用表达式树实现// int a,b;

ParameterExpression a = Expression.Parameter(typeof(int), "a");

ParameterExpression b = Expression.Parameter(typeof(int), "b");

// a = 21,b = 10;

BinaryExpression setA = Expression.Assign(a, Expression.Constant(21));

BinaryExpression setB = Expression.Assign(b, Expression.Constant(20));

// Console.Write("a == b:");

// Console.WriteLine(a == b);

MethodCallExpression call1 = Expression.Call(null,

typeof(Console).GetMethod("Write", new Type[] { typeof(string) }),

Expression.Constant("a == b:"));

MethodCallExpression call11 = Expression.Call(null,

typeof(Console).GetMethod("WriteLine", new Type[] { typeof(bool) }),

Expression.Equal(a, b));

// Console.Write("a 

// Console.WriteLine(a 

MethodCallExpression call2 = Expression.Call(null,

typeof(Console).GetMethod("Write", new Type[] { typeof(string) }),

Expression.Constant("a 

MethodCallExpression call22 = Expression.Call(null,

typeof(Console).GetMethod("WriteLine", new Type[] { typeof(bool) }),

Expression.LessThan(a, b));

// Console.Write("a > b :");

// Console.WriteLine(a > b);

MethodCallExpression call3 = Expression.Call(null,

typeof(Console).GetMethod("Write", new Type[] { typeof(string) }),

Expression.Constant("a > b :"));

MethodCallExpression call33 = Expression.Call(null,

typeof(Console).GetMethod("WriteLine", new Type[] { typeof(bool) }),

Expression.GreaterThan(a, b));

// 改变 a 和 b 的值

// a = 5;

// b = 20;

BinaryExpression setAa = Expression.Assign(a, Expression.Constant(5));

BinaryExpression setBb = Expression.Assign(b, Expression.Constant(20));

// Console.Write("a <= b:");

// Console.WriteLine(a = a);

MethodCallExpression call5 = Expression.Call(null,

typeof(Console).GetMethod("Write", new Type[] { typeof(string) }),

Expression.Constant("a >= b:"));

MethodCallExpression call55 = Expression.Call(null,

typeof(Console).GetMethod("WriteLine", new Type[] { typeof(bool) }),

Expression.GreaterThanOrEqual(a, b));

BlockExpression block = Expression.Block(new ParameterExpression[] { a, b },

setA,

setB,

call1,

call11,

call2,

call22,

call3,

call33,

setAa,

setBb,

call4,

call44,

call5,

call55

);

Expressionlambda = Expression.Lambda(block);

lambda.Compile()();

Console.ReadKey();

生成的表达式树如下.Lambda #Lambda1() {

.Block(

System.Int32 $a,

System.Int32 $b) {

$a = 21;

$b = 20;

.Call System.Console.Write("a == b:");

.Call System.Console.WriteLine($a == $b);

.Call System.Console.Write("a 

.Call System.Console.WriteLine($a 

.Call System.Console.Write("a > b :");

.Call System.Console.WriteLine($a > $b);

$a = 5;

$b = 20;

.Call System.Console.Write("a = b:");

.Call System.Console.WriteLine($a >= $b)

}

}

三,逻辑运算符

&&、||、!运算符描述&&称为逻辑与运算符。如果两个操作数都非零,则条件为真。

||称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。

!称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。

逻辑运算符的运行,结果是 true 或 false。逻辑运算符表达式树&&Expression.AndAlso()

||Expression.OrElse()

!Expression.Not()int a = 10;

int b = 11;

Console.Write("[a == b && a > b]:");

Console.WriteLine(a == b && a > b);

Console.Write("[a > b || a == b]:");

Console.WriteLine(a > b || a == b);

Console.Write("[!(a == b)]:");

Console.WriteLine(!(a == b));

Console.ReadKey();

使用表达式树编写//int a = 10;

//int b = 11;

ParameterExpression a = Expression.Parameter(typeof(int), "a");

ParameterExpression b = Expression.Parameter(typeof(int), "b");

BinaryExpression setA = Expression.Assign(a, Expression.Constant(10));

BinaryExpression setB = Expression.Assign(b, Expression.Constant(11));

//Console.Write("[a == b && a > b]:");

//Console.WriteLine(a == b && a > b);

MethodCallExpression call1 = Expression.Call(null, typeof(Console).GetMethod("Write", new Type[] { typeof(string) }), Expression.Constant("[a == b && a > b]:"));

MethodCallExpression call2 = Expression.Call(

null,

typeof(Console).GetMethod("WriteLine", new Type[] { typeof(bool) }),

Expression.AndAlso(Expression.Equal(a, b), Expression.GreaterThan(a, b))

);

//Console.Write("[a > b || a == b]:");

//Console.WriteLine(a > b || a == b);

MethodCallExpression call3 = Expression.Call(null, typeof(Console).GetMethod("Write", new Type[] { typeof(string) }), Expression.Constant("[a > b || a == b]:"));

MethodCallExpression call4 = Expression.Call(

null,

typeof(Console).GetMethod("WriteLine", new Type[] { typeof(bool) }),

Expression.OrElse(Expression.Equal(a, b), Expression.GreaterThan(a, b))

);

//Console.Write("[!(a == b)]:");

//Console.WriteLine(!(a == b));

MethodCallExpression call5 = Expression.Call(null, typeof(Console).GetMethod("Write", new Type[] { typeof(string) }), Expression.Constant("[!(a == b)]:"));

MethodCallExpression call6 = Expression.Call(

null,

typeof(Console).GetMethod("WriteLine", new Type[] { typeof(bool) }),

Expression.Not(Expression.Equal(a, b))

);

BlockExpression block = Expression.Block(

new ParameterExpression[] { a, b },

setA,

setB,

call1,

call2,

call3,

call4,

call5,

call6

);

Expressionlambda = Expression.Lambda(block);

lambda.Compile()();

Console.ReadKey();

生成的表达式树如下.Lambda #Lambda1() {

.Block(

System.Int32 $a,

System.Int32 $b) {

$a = 10;

$b = 11;

.Call System.Console.Write("[a == b && a > b]:");

.Call System.Console.WriteLine($a == $b && $a > $b);

.Call System.Console.Write("[a > b || a == b]:");

.Call System.Console.WriteLine($a == $b || $a > $b);

.Call System.Console.Write("[!(a == b)]:");

.Call System.Console.WriteLine(!($a == $b))

}

}

四,位运算符

&、|、^、~、

|如果存在于任一操作数中,二进制 OR 运算符复制一位到结果中。(A | B) 将得到 61,即为 0011 1101

^如果存在于其中一个操作数中但不同时存在于两个操作数中,二进制异或运算符复制一位到结果中。(A ^ B) 将得到 49,即为 0011 0001

~按位取反运算符是一元运算符,具有"翻转"位效果,即0变成1,1变成0,包括符号位。(~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。

<

>>二进制右移运算符。左操作数的值向右移动右操作数指定的位数。A >> 2 将得到 15,即为 0000 1111

限于篇幅,就写示例了。位运算符表达式树&Expression.Add(Expression left, Expression right)

|Expression.Or(Expression left, Expression right)

^Expression.ExclusiveOr(Expression expression)

~Expression.OnesComplement( Expression expression)

<

>>Expression.RightShift(Expression left, Expression right)

五,赋值运算符运算符描述实例=简单的赋值运算符,把右边操作数的值赋给左边操作数C = A + B 将把 A + B 的值赋给 C

+=加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数C += A 相当于 C = C + A

-=减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数C -= A 相当于 C = C - A

*=乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数C *= A 相当于 C = C * A

/=除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数C /= A 相当于 C = C / A

%=求模且赋值运算符,求两个操作数的模赋值给左边操作数C %= A 相当于 C = C % A

<<=左移且赋值运算符C <<= 2 等同于 C = C << 2

>>=右移且赋值运算符C >>= 2 等同于 C = C >> 2

&=按位与且赋值运算符C &= 2 等同于 C = C & 2

^=按位异或且赋值运算符C ^= 2 等同于 C = C ^ 2

|=按位或且赋值运算符C |= 2 等同于 C = C | 2

限于篇幅,请自行领略... ...运算符表达式树=Expression.Assign

+=Expression.AddAssign

-=Expression.SubtractAssign

*=Expression.MultiplyAssign

/=Expression.DivideAssign

%=Expression.ModuloAssign

<<=Expression.LeftShiftAssign

>>=Expression.RightShiftAssign

&=Expression.AndAssign

^=Expression.ExclusiveOrAssign

|=Expression.OrAssign

^= ,注意有两种意思一种是位运算符的异或(ExclusiveOrAssign),一种是算术运算符的幂运算(PowerAssign)。

六,其他运算符运算符描述实例sizeof()返回数据类型的大小。sizeof(int),将返回 4.

typeof()返回 class 的类型。typeof(StreamReader);

&返回变量的地址。&a; 将得到变量的实际地址。

*变量的指针。*a; 将指向一个变量。

? :条件表达式如果条件为真 ? 则为 X : 否则为 Y

is判断对象是否为某一类型。If( Ford is Car) // 检查 Ford 是否是 Car 类的一个对象。

as强制转换,即使转换失败也不会抛出异常。Object obj = new StringReader("Hello"); StringReader r = obj as StringReader;

表达式树里面我没有找到这些运算符的如何编写,如果你找到了,欢迎告诉我。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值