c#五类运算符使用表达式树进行操作-kb88凯时官网登录

来自:网络
时间:2023-01-01
阅读:
免费资源网 - https://freexyz.cn/

在 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);
            expression lambda = 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
                );
            expression lambda = 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 < 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;
            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 < b :");
            // console.writeline(a < b);
            methodcallexpression call2 = expression.call(null,
                typeof(console).getmethod("write", new type[] { typeof(string) }),
                expression.constant("a < b :"));
            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 <= b);
            methodcallexpression call4 = expression.call(null,
                typeof(console).getmethod("write", new type[] { typeof(string) }),
                expression.constant("a <= b:"));
            methodcallexpression call44 = expression.call(null,
                typeof(console).getmethod("writeline", new type[] { typeof(bool) }),
                expression.lessthanorequal(a, b));
            // console.write("a >= b:");
            // console.writeline(b >= 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
                );
            expression lambda = 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 < 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)
    }
}

三,逻辑运算符

&&、||、!

运算符描述
&&称为逻辑与运算符。如果两个操作数都非零,则条件为真。
||称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。
!称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。

逻辑运算符的运行,结果是 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
                );
            expression lambda = 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))
    }
}

四,位运算符

&、|、^、~、<<、>>

运算符描述实例
&如果同时存在于两个操作数中,二进制 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#五类运算符使用表达式树进行操作的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持。

免费资源网 - https://freexyz.cn/
返回顶部
顶部
网站地图