服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - 带你一文了解C#中的Expression

带你一文了解C#中的Expression

2022-12-13 12:21RyzenAdorer C#

c#中有Expression,即表达式,通过Expression可以动态构造代码,并编译执行,下面这篇文章主要给大家介绍了关于C#中Expression的相关资料,需要的朋友可以参考下

前言

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

IQueryable则用Expression来作为传参:

?
1
2
3
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

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

?
1
2
3
4
5
Expression<Func<int, int>> expression = (num) => num + 5;
Console.WriteLine($"NodeType:{expression.NodeType}");
Console.WriteLine($"Body:{expression.Body}");
Console.WriteLine($"Body Type: {expression.Body.GetType()}");
Console.WriteLine($"Body NodeType: {expression.Body.NodeType}");

输出如下:

NodeType:Lambda

Body:(num + 5)

Body Type: System.Linq.Expressions.SimpleBinaryExpression

Body NodeType: Add

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

?
1
2
3
4
5
6
7
8
if (expression.NodeType == ExpressionType.Lambda)
{
    var lambda = (LambdaExpression)expression;
    var parameter = lambda.Parameters.Single();
    Console.WriteLine($"parameter.Name:{parameter.Name}");
    Console.WriteLine($"parameter.Type:{parameter.Type}");
    Console.WriteLine($"parameter.ReturnType:{lambda.ReturnType}");
}

输出如下:

parameter.Name:num

parameter.Type:System.Int32

parameter.ReturnType:System.Int32

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
if (expression.Body.NodeType == ExpressionType.Add)
{
    var binaryExpreesion = (BinaryExpression)expression.Body;
 
    
    Console.WriteLine($"Left Type:{binaryExpreesion.Left.GetType()}");
    Console.WriteLine($"Left NodeType:{binaryExpreesion.Left.NodeType}");
 
    Console.WriteLine($"Right Type:{binaryExpreesion.Right.GetType()}");
    Console.WriteLine($"Right NodeType:{binaryExpreesion.Right.NodeType}");
 
    if (binaryExpreesion.Left is ParameterExpression parameterExpreesion)
    {
        Console.WriteLine($"parameterExpreesion.Name:{parameterExpreesion.Name}");
        Console.WriteLine($"parameterExpreesion.Type:{parameterExpreesion.Type}");
    }
 
    if (binaryExpreesion.Right is ConstantExpression constantExpreesion)
    {
        Console.WriteLine($"constantExpreesion.Value:{constantExpreesion.Value}" );
    }
}

输出如下:

Left Type:System.Linq.Expressions.PrimitiveParameterExpression`1[System.Int32]

Left NodeType:Parameter

Right Type:System.Linq.Expressions.ConstantExpression

Right NodeType:Constant

parameterExpreesion.Name:num

parameterExpreesion.Type:System.Int32

constantExpreesion.Value:5

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

?
1
2
var @delegate = expression.Compile();
Console.WriteLine(@delegate?.Invoke(2));

输出:

7 //2+5

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

带你一文了解C#中的Expression

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

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

带你一文了解C#中的Expression

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var parameterExpreesion1 = Expression.Parameter(typeof(int), "num");
BinaryExpression binaryExpression1 = Expression.MakeBinary(ExpressionType.Add, parameterExpreesion1, Expression.Constant(5));
Expression<Func<int, int>> expression1 = Expression.Lambda<Func<int, int>>(binaryExpression1, parameterExpreesion1);
 
if (expression1.Body.NodeType == ExpressionType.Add)
{
    var binaryExpreesion1 = (BinaryExpression)expression1.Body;
 
 
    Console.WriteLine($"Left Type:{binaryExpreesion1.Left.GetType()}");
    Console.WriteLine($"Left NodeType:{binaryExpreesion1.Left.NodeType}");
 
    Console.WriteLine($"Right Type:{binaryExpreesion1.Right.GetType()}");
    Console.WriteLine($"Right NodeType:{binaryExpreesion1.Right.NodeType}");
 
    if (binaryExpreesion1.Left is ParameterExpression parameterExpreesion2)
    {
        Console.WriteLine($"parameterExpreesion.Name:{parameterExpreesion2.Name}");
        Console.WriteLine($"parameterExpreesion.Type:{parameterExpreesion2.Type}");
    }
 
    if (binaryExpreesion1.Right is ConstantExpression constantExpreesion1)
    {
        Console.WriteLine($"constantExpreesion.Value:{constantExpreesion1.Value}");
    }
 
    var @delegate1 = expression1.Compile();
    Console.WriteLine(@delegate1(2));

输出结果:

Left Type:System.Linq.Expressions.PrimitiveParameterExpression`1[System.Int32]

Left NodeType:Parameter

Right Type:System.Linq.Expressions.ConstantExpression

Right NodeType:Constant

parameterExpreesion.Name:num

parameterExpreesion.Type:System.Int32

constantExpreesion.Value:5

result:7

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

参考

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

源码

BlogCodeSample/ExpressionSample at main · ZhengDaoWang/BlogCodeSample

总结

到此这篇关于C#中Expression的文章就介绍到这了,更多相关C#的Expression内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.cnblogs.com/ryzen/p/15674630.html

延伸 · 阅读

精彩推荐
  • C#C#给Excel添加水印实例详解

    C#给Excel添加水印实例详解

    这篇文章主要介绍了C#给Excel添加水印实例的相关资料,需要的朋友可以参考下...

    Yesi11812021-12-07
  • C#C# 如何生成 DataMatrix 格式的二维码

    C# 如何生成 DataMatrix 格式的二维码

    该文主要是利用OnBarcode.dll 生成DataMatrix 格式的二维码的一些简单方法和操作技巧,对C# 如何生成 DataMatrix 格式的二维码相关知识感兴趣的朋友一起看看吧...

    艾野草11512022-12-07
  • C#C#中txt数据写入的几种常见方法

    C#中txt数据写入的几种常见方法

    这篇文章主要给大家介绍了关于C#中txt数据写入的几种常见方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需...

    小帅帅呆了17662022-10-12
  • C#winform 实现选择文件和选择文件夹对话框的简单实例

    winform 实现选择文件和选择文件夹对话框的简单实例

    下面小编就为大家带来一篇winform 实现选择文件和选择文件夹对话框的简单实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小...

    C#教程网7982021-12-21
  • C#C#创建一个小型Web Server(Socket实现)

    C#创建一个小型Web Server(Socket实现)

    这篇文章主要介绍了关于C#利用Socket实现创建一个小型Web Server的相关资料,文中通过示例代码介绍的很详细,需要的朋友可以参考借鉴,下面来一起看看吧...

    千一网络6752021-12-27
  • C#C#窗体程序实现全屏及取消全屏步骤

    C#窗体程序实现全屏及取消全屏步骤

    这篇文章主要介绍了C#窗体程序实现全屏及取消全屏步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    影_汐4192022-10-20
  • C#C#创建SQLite控制台应用程序详解

    C#创建SQLite控制台应用程序详解

    这篇文章主要为大家详细介绍了C#创建SQLite控制台应用程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    cnc6142022-01-17
  • C#C# 函数覆盖总结学习(推荐)

    C# 函数覆盖总结学习(推荐)

    下面小编就为大家带来一篇C# 函数覆盖总结学习(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    C#教程网11822021-11-22