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

表达式树练习实践:C# 五类运算符的表达式树表达,第1张

概述表达树练习实践:C 运算符 [TOC] 在 C 中,算术运算符,有以下类型 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 其他运算符 这些运算符根据参数的多少,可以分作一元运算符、二元运 表达式树练习实践:C# 运算符

目录表达式树练习实践:C# 运算符一,算术运算符+ 与 Add()- 与 Subtract()乘除、取模自增自减二,关系运算符==、!=、>、<、>=、<=三,逻辑运算符&&、||、!四,位运算符&、|、^、~、<<、>>五,赋值运算符六,其他运算符

在 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<Action<int,int>> lambda = Expression.Lambda<Action<int,int>>(method,a,b);            lambda.Compile()(100,200);            Console.ReadKey();

如果想复杂一些,使用 来执行:

            ParameterExpression a = 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,ab);            // 以块的形式执行代码,相当于{ }            // 不需要纠结这里,后面会有详细说明,重点是上面            var call = Expression.Block(new ParameterExpression[] { a,b },aa,bb,method);            Expression<Action> lambda = Expression.Lambda<Action>(call);            lambda.Compile()();

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

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

那么,如何通过表达式树执行运算,获取执行结果呢?

            ParameterExpression a = Expression.Parameter(typeof(int),b);            Expression<Func<int,int,int>> lambda = Expression.Lambda<Func<int,int>>(ab,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),"b");            // ab = a - b            BinaryExpression ab = Expression.Subtract(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),"b");            // ab = a % b            BinaryExpression ab = Expression.Modulo(a,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),"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,a);            MethodCallExpression callB = Expression.Call(null,b);            BlockExpression block = Expression.Block(                new ParameterExpression[] { a,setA,setB,callA,callB                );            Expression<Action> lambda = Expression.Lambda<Action>(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,b);            BlockExpression block = Expression.Block(                aa,callB                );            Expression<Action<int,int>>(block,b);            lambda.Compile()(10,10);            Console.ReadKey();

生成的表达式树如下

.Lambda #Lambda1<System.Action`2[system.int32,system.int32]>(    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 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,SetA,SetB,callB                );            Expression<Action<int>> lambda = Expression.Lambda<Action<int>>(block,c);            lambda.Compile()(10);            Console.ReadKey();

为什么这里要多加一个 c 呢?我们来看看生成的表达式树

.Lambda #Lambda1<System.Action`1[system.int32]>(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,10);            Console.ReadKey();
.Lambda #Lambda1<System.Action`2[system.int32,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 < b :");            Console.Writeline(a < b);            Console.Write("a > b :");            Console.Writeline(a > b);            // 改变 a 和 b 的值             a = 5;            b = 20;            Console.Write("a <= b:");            Console.Writeline(a <= b);            Console.Write("a >= b:");            Console.Writeline(b >= a);            Console.ReadKey();

使用表达式树实现

            // int a,"b");            // a = 21,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,new Type[] { typeof(bool) }),Expression.Equal(a,b));            // Console.Write("a < b :");            // Console.Writeline(a < b);            MethodCallExpression call2 = Expression.Call(null,Expression.Constant("a < b :"));            MethodCallExpression call22 = Expression.Call(null,Expression.Lessthan(a,b));            // Console.Write("a > b :");            // Console.Writeline(a > b);            MethodCallExpression call3 = Expression.Call(null,Expression.Constant("a > b :"));            MethodCallExpression call33 = Expression.Call(null,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 <= b);            MethodCallExpression call4 = Expression.Call(null,Expression.Constant("a <= b:"));            MethodCallExpression call44 = Expression.Call(null,Expression.LessthanorEqual(a,b));            // Console.Write("a >= b:");            // Console.Writeline(b >= a);            MethodCallExpression call5 = Expression.Call(null,Expression.Constant("a >= b:"));            MethodCallExpression call55 = Expression.Call(null,Expression.GreaterThanorEqual(a,b));            BlockExpression block = Expression.Block(new ParameterExpression[] { a,call1,call11,call2,call22,call3,call33,setAa,setBb,call4,call44,call5,call55                );            Expression<Action> lambda = Expression.Lambda<Action>(block);            lambda.Compile()();            Console.ReadKey();

生成的表达式树如下

.Lambda #Lambda1<System.Action>() {    .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 < b :");        .Call System.Console.Writeline($a < $b);        .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);        .Call System.Console.Write("a >= b:");        .Call System.Console.Writeline($a >= $b)    }}
三,逻辑运算符@H_90_404@&&、||、!
运算符描述
&&称为逻辑与运算符。如果两个 *** 作数都非零,则条件为真。
||称为逻辑或运算符。如果两个 *** 作数中有任意一个非零,则条件为真。
!称为逻辑非运算符。用来逆转 *** 作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。

逻辑运算符的运行,结果是 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),"b");            BinaryExpression setA = Expression.Assign(a,Expression.Constant(11));            //Console.Write("[a == b && a > b]:");            //Console.Writeline(a == b && a > b);            MethodCallExpression call1 = Expression.Call(null,Expression.Constant("[a == b && a > b]:"));            MethodCallExpression call2 = Expression.Call(                null,Expression.AndAlso(Expression.Equal(a,b),b))                );            //Console.Write("[a > b || a == b]:");            //Console.Writeline(a > b || a == b);            MethodCallExpression call3 = Expression.Call(null,Expression.Constant("[a > b || a == b]:"));            MethodCallExpression call4 = Expression.Call(                null,Expression.OrElse(Expression.Equal(a,b))                );            //Console.Write("[!(a == b)]:");            //Console.Writeline(!(a == b));            MethodCallExpression call5 = Expression.Call(null,Expression.Constant("[!(a == b)]:"));            MethodCallExpression call6 = Expression.Call(                null,Expression.Not(Expression.Equal(a,b))                );            BlockExpression block = Expression.Block(                new ParameterExpression[] { a,call6                );            Expression<Action> lambda = Expression.Lambda<Action>(block);            lambda.Compile()();            Console.ReadKey();

生成的表达式树如下

.Lambda #Lambda1<System.Action>() {    .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))    }}
四,位运算符&、|、^、~、<<、>>
运算符描述实例
&如果同时存在于两个 *** 作数中,二进制 AND 运算符复制一位到结果中。(A & B) 将得到 12,即为 0000 1100
|如果存在于任一 *** 作数中,二进制 OR 运算符复制一位到结果中。(A | B) 将得到 61,即为 0011 1101
^如果存在于其中一个 *** 作数中但不同时存在于两个 *** 作数中,二进制异或运算符复制一位到结果中。(A ^ B) 将得到 49,即为 0011 0001
~按位取反运算符是一元运算符,具有"翻转"位效果,即0变成1,1变成0,包括符号位。(~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。
<<二进制左移运算符。左 *** 作数的值向左移动右 *** 作数指定的位数。A << 2 将得到 240,即为 1111 0000
>>二进制右移运算符。左 *** 作数的值向右移动右 *** 作数指定的位数。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.leftShift(Expression left,Expression right)
>>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;

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

总结

以上是内存溢出为你收集整理的表达式树练习实践:C# 五类运算符的表达式树表达全部内容,希望文章能够帮你解决表达式树练习实践:C# 五类运算符的表达式树表达所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1213945.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存