飙血推荐
  • HTML教程
  • MySQL教程
  • JavaScript基础教程
  • php入门教程
  • JavaScript正则表达式运用
  • Excel函数教程
  • UEditor使用文档
  • AngularJS教程
  • ThinkPHP5.0教程

了解C#的Expression

时间:2021-12-13  作者:ryzen  

我们书接上文,我们在了解LINQ下面有说到在本地查询IEnumerbale主要是用委托来作为传参,而解析型查询
IQueryable则用Expression来作为传参:


public static IEnumerable<T> Where<T>(this IEnumerable<T> enumable, Func<T, bool> func)

public static IQueryable<T> Where<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> func)


那么我们就来聊聊有关表达式Expression里面的东西吧

Expression与Expression Tree

首先我们来写下一些代码:

Expression<Func<int, int>> expression = (num) => num + 5;
域名eLine($"NodeType:{域名Type}");
域名eLine($"Body:{域名}");
域名eLine($"Body Type: {域名ype()}");
域名eLine($"Body NodeType: {域名Type}");

输出如下:

NodeType:Lambda
Body:(num + 5)
Body Type: 域名域名leBinaryExpression
Body NodeType: Add

我们将expression转为LambdaExpression看看都有啥:

if (域名Type == 域名da)
{
    var lambda = (LambdaExpression)expression;
    var parameter = 域名le();
    域名eLine($"域名:{域名}");
    域名eLine($"域名:{域名}");
    域名eLine($"域名rnType:{域名rnType}");
}

输出如下:

域名:num
域名:域名2
域名rnType:域名2

由于我们知道域名BinaryExpression,那么我们就将其转为它,然后我们继续看下去:

if (域名Type == 域名)
{
    var binaryExpreesion = (BinaryExpression)域名;

    
    域名eLine($"Left Type:{域名ype()}");
    域名eLine($"Left NodeType:{域名Type}");

    域名eLine($"Right Type:{域名ype()}");
    域名eLine($"Right NodeType:{域名Type}");

    if (域名 is ParameterExpression parameterExpreesion)
    {
        域名eLine($"域名:{域名}");
        域名eLine($"域名:{域名}");
    }

    if (域名t is ConstantExpression constantExpreesion)
    {
        域名eLine($"域名e:{域名e}" );
    }
}

输出如下:

Left Type:域名域名itiveParameterExpression`1[域名2]
Left NodeType:Parameter
Right Type:域名域名tantExpression
Right NodeType:Constant
域名:num
域名:域名2
域名e:5

最后我们将表达式树转为委托:

var @delegate = 域名ile();
域名eLine(@delegate?.Invoke(2));

输出:

7 //2+5

实际上,通过Expression<Func<int, int>> expression = (num) => num + 5;,赋值后的expression 变成了一个表达式树,它的结构是这样的:

而有意思的是二元表达式树BinaryExpression是一个二叉树,而LambdaExpression则是一个支持参数的表达式,能够通过其Parameters属性知道传入的参数的类型和数量,通过ReturnType知道返回值是什么类型

而我们再看看整个关于Expression的继承关系链:

因此,我们也可以显式的通过各自Expreesion的实现子类来创建跟lambda表达式一样的结果:

var parameterExpreesion1 = 域名meter(typeof(int), "num");
BinaryExpression binaryExpression1 = 域名Binary(域名, parameterExpreesion1, 域名tant(5));
Expression<Func<int, int>> expression1 = 域名da<Func<int, int>>(binaryExpression1, parameterExpreesion1);

if (域名Type == 域名)
{
    var binaryExpreesion1 = (BinaryExpression)域名;


    域名eLine($"Left Type:{域名ype()}");
    域名eLine($"Left NodeType:{域名Type}");

    域名eLine($"Right Type:{域名ype()}");
    域名eLine($"Right NodeType:{域名Type}");

    if (域名 is ParameterExpression parameterExpreesion2)
    {
        域名eLine($"域名:{域名}");
        域名eLine($"域名:{域名}");
    }

    if (域名t is ConstantExpression constantExpreesion1)
    {
        域名eLine($"域名e:{域名e}");
    }

    var @delegate1 = 域名ile();
    域名eLine(@delegate1(2));

输出结果:

Left Type:域名域名itiveParameterExpression`1[域名2]
Left NodeType:Parameter
Right Type:域名域名tantExpression
Right NodeType:Constant
域名:num
域名:域名2
域名e:5
result:7

我们则发现,结果是一模一样的,但是费劲了很多,因此用lamda构建表达式树是一个非常愉快的语法糖,让你能够愉快的在使用表达式和表达式树

参考

  • 《C#7.0核心技术指南》

源码

  • BlogCodeSample/ExpressionSample at main · ZhengDaoWang/BlogCodeSample

标签:编程
湘ICP备14001474号-3  投诉建议:234161800@qq.com   部分内容来源于网络,如有侵权,请联系删除。