c#: 表达式树的简化

环境:

  • .net 6

一、问题?

有下面的表达式:

var nums = new List<int> { 1, 2, 3 };
Expression<Func<int, bool>> exp = i => i > nums.Max();

我们知道,它其实就是:exp = i => i > 3;
那么问题是,我们如何将它改造成这样呢?

在orm解析lambda生成sql时,也经常遇到这样的窘境:

var scores = new List<Person> { new Person { Id = 1, Score = 60 } };
var sql = orm.Select<Person>().Where(i => i.Score > scores.Select(i=>i.Score).Max() || i.Score == 100).ToSql();
//error: 
// System.Exception:“未实现函数表达式 value(Program+<>c__DisplayClass0_0).scores.Select(i => i.Score).Max() 解析,如果正在操作导航属性集合,请使用 .AsSelect().Max()”public class Person
{public int Id { get; set; }public double Score { get; set; }
}

所以,就有了个想法:能不能对表达式进行简化呢?
就比如上面的可以改造成:orm.Select<Person>().Where(i => i.Score > 60 || i.Score == 100).ToSql();

二、表达式树简化原理

lambda表达式是表达式树的根, 它可能会有参数列表, 其子孙节点可能会引用这些参数, 也可能没有引用, 将没有引用的分支编译求值, 将结果再“放回”表达式中即可!

还是以下面的表达式为例:

var nums = new List<int> { 1, 2, 3 };
Expression<Func<int, bool>> exp = i => i > nums.Max();

在节点 > 的右侧 nums.Max() 没有引用参数列表, 那么它就可以被简化, 简化后就是:
exp = i => i > 3;

再看如下:

var nums = new List<int> { 1, 2, 3 };
Expression<Func<int, bool>> expr = i => i > nums.Max() || nums.Count > 0;

我们不仅可以将 || 右侧的简化为 true, 还可以根据||的短路特性对整体进行简化, 结果如下:
exp = i => true

三、表达式树的树状图

我们知道有各种各样的表达式类型, 如: +-/*Call/MemberInit等。
无论哪种类型, 都可以将它们抽象成一棵树, 如:
Call类型的表达式, 可以看成:

在这里插入图片描述

表达式的嵌套:
lambda表达式有可能会嵌套lambda, 如:

var nums = new List<int> { 1, 2, 3 };
Expression<Func<int>> expr = () => Filter(nums, i => i > 1);static int Filter(List<int> nums, Func<int, bool> func)
{return nums.First(i => func(i));
}

它的结构树如下:
在这里插入图片描述

这个是函数接受委托的, 还有函数接受lambda的,如:

var nums = new List<int> { 1, 2, 3 };
Expression<Func<int>> expr = () => Filter(nums, i => i > 1);
static int Filter(List<int> nums, Expression<Func<int, bool>> expression)
{return nums.First(i => expression.Compile()(i));
}

此时,它的结构树如下:
在这里插入图片描述

四、成品代码

在DotNetCommon.Core``已封装好了表达式树简化的方法,如下:
在这里插入图片描述
更多细节,参考:《DotNetCommon源码》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/676074.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

redis双写一致

redis双写一致&#xff0c;指的是redis缓存与mysql数据同步 双写一致常见方案有很多&#xff1a; 同步双写&#xff1a;更新完mysql后立即同时更新redis mq同步&#xff1a;程序在更新完mysql后&#xff0c;投递消息到中间键mq&#xff0c;一个程序监听mq&#xff0c;获得消…

商汤科技「日日新4.0」正式发布,多维度升级大模型体系,能力比肩GPT-4!

文 | BFT机器人 近日&#xff0c;商汤科技正式发布「日日新SenseNova 4.0」&#xff0c;宣告大模型体系多维度全面升级。这款模型具备更全面的知识覆盖、更可靠的推理能力&#xff0c;以及更优越的长文本理解和数字推理能力。同时&#xff0c;它还支持跨模态交互&#xff0c;为…

【跳槽须知】关于企业所签订的竞业协议你知道多少?

年后跳槽须知自己签订的合同中是否存在竞业协议&#xff0c;谨防协议造成经济损失 &#x1f413; 什么是竞业协议 竞业协议时用于保护自己的权益&#xff0c;在员工离职时决定是否启动的一种协议&#xff0c;避免一些掌握公司机密的一些重要岗位人才流入竞争对手的公司&#xf…

解决MapboxGL的Popup不支持HTMLDiv元素的问题

解决MapboxGL的Popup不支持HTMLDiv元素的问题 官网给出的文档是不支持HTMLDivElement的&#xff0c;只支持HTML标签。 如果单纯的只显示字符串&#xff0c;那就没问题&#xff0c;如果想在Popup中使用更强大的功能&#xff0c;此时就不行了&#xff0c;下面是源码的一部分显示…

GPT-4登场:多模态能力革新,提升ChatGPT与必应体验,开放API助力游戏革新

GPT-4登场&#xff1a;多模态能力革新&#xff0c;提升ChatGPT与必应体验&#xff0c;开放API助力游戏革新 引言 在人工智能领域&#xff0c;GPT-4的发布标志着一个新时代的到来。这一多模态大模型不仅在技术性能上实现了飞跃&#xff0c;更在功能层面带来全新的突破。GPT-4的…

WordPress如何实现随机显示一句话经典语录?怎么添加到评论框中?

我们在一些WordPress网站的顶部或侧边栏或评论框中&#xff0c;经常看到会随机显示一句经典语录&#xff0c;他们是怎么实现的呢&#xff1f; 其实&#xff0c;boke112百科前面跟大家分享的『WordPress集成一言&#xff08;Hitokoto&#xff09;API经典语句功能』一文中就提供…

【Linux】基于单例模式懒汉实现方式的线程池

基于单例模式懒汉实现方式的线程池 一、LockGuard.hpp #pragma once #include <iostream> #include <pthread.h> class Mutex//锁的对象 { public:Mutex(pthread_mutex_t* lock_pnullptr):_lock_p(lock_p){}~Mutex(){}void lock(){if(_lock_p){pthread_mutex_loc…

FastAPI使用ORJSONResponse作为默认的响应类型

FastAPI默认使用Python的标准库来做json解析&#xff0c;如果换成rust编写的orjson&#xff0c;速度上会快一些 1. 安装依赖 pip install orjson 2. 设置为默认响应类型 from fastapi.responses import ORJSONResponseapp FastAPI(titlexxx, default_response_classORJSON…

nginx+flask+Gunicorn反代理服务拿不到真实IP的解决

背景 本人在宝塔linux环境&#xff0c;要部署flask的简单后端并且用Ngnix反代理&#xff0c;用Gunicorn框架部署。&#xff08;o(╥﹏╥)o中间磕磕绊绊总算部署上去了&#xff0c;需要了解Gunicorn怎么部署的朋友&#xff0c;评论区留言&#xff0c;我加补一篇介绍&#xff09;…

32I2C通信协议

异步时序的&#xff1a;非常依赖硬件外设的支持&#xff0c;比如串口是很难用软件来模拟的&#xff1b;但节省了一根时钟线的资源 同步时序可以极大地降低单片机对硬件电路的依赖&#xff0c;时钟线停止了&#xff0c;发送方和接收方都会停止 一.I2C通信协议简介 二.硬件电路…

[WUSTCTF2020]朴实无华(特详解)

一开始说header出问题了 就先dirsaerch扫一遍 发现robot.txt 访问一下 去看看&#xff0c;好好好&#xff0c;肯定不是得 他一开始说header有问题&#xff0c;不妨抓包看看&#xff0c;果然有东西 访问看看&#xff0c;乱码修复一下&#xff0c;在之前的博客到过 <img src…

Mysql——更新数据

注&#xff1a;文章参考&#xff1a; MySQL 更新数据 不同条件(批量)更新不同值_update批量更新同一列不同值-CSDN博客文章浏览阅读2w次&#xff0c;点赞20次&#xff0c;收藏70次。一般在更新时会遇到以下场景&#xff1a;1.全部更新&#xff1b;2.根据条件更新字段中的某部分…

div 2_div 3_ div 4_刷题刷题刷题

关于 div 4 的思考 感觉好像可以写到 F 都不需要什么算法知识 关于 div 3 的思考 感觉可以做到 E 好像都不需要什么算法知识 关于 div 2 的思考 好像做到 C 都不需要什么算法知识 赶紧刷题就行&#xff0c;加油加油

【C++】实现一个二叉搜索树

目录 二叉搜索树的概念 1.结点定义 2.构造、析构、拷贝构造、赋值重载 3.插入、删除、查找、排序 3.1插入 3.2插入递归版 3.3查找指定值 3.3查找指定值递归版 3.4中序遍历 3.5删除 最后 二叉搜索树的概念 二叉搜索树又称为二叉排序树或二叉查找树&#xff0c;它或者…

Markdown:简洁高效的文本标记语言

引言 在当今信息爆炸的时代&#xff0c;我们需要一种简洁、高效的文本标记语言来排版和发布内容。Markdown应运而生&#xff0c;它是一种轻量级的文本标记语言&#xff0c;以其简单易学、易读易写的特点&#xff0c;成为了广大写作者的首选工具。本文将介绍Markdown的语法优缺…

设计模式(行为型模式)观察者模式

目录 一、简介二、观察者模式2.1、事件接口及其实现2.2、观察者接口及其实现2.3、主题接口及其实现2.4、使用 三、优点与缺点 一、简介 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为设计模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;当一个对象…

Composition Local

1.显示传参 package com.jmj.jetpackcomposecompositionlocalimport org.junit.Testimport org.junit.Assert.*/*** 显示传参*/ class ExplicitText {private fun Layout(){var color:String "黑色";//参数需要通过层层传递&#xff0c;比较繁琐Text(color)Grid(c…

B2081 与 7 无关的数(洛谷)

题目描述 一个正整数&#xff0c;如果它能被 7 整除&#xff0c;或者它的十进制表示法中某一位上的数字为 7&#xff0c;则称其为与 7 相关的数。现求所有小于等于 n(n<100) 与 7 无关的正整数的平方和。 输入格式 输入为一行&#xff0c;正整数 n(n<100)。 输出格式…

Redis篇之过期淘汰策略

一、数据的过期策略 1.什么是过期策略 Redis对数据设置数据的有效时间&#xff0c;数据过期以后&#xff0c;就需要将数据从内存中删除掉。可以按照不同的规则进行删除&#xff0c;这种删除规则就被称之为数据的删除策略&#xff08;数据过期策略&#xff09;。 2.过期策略-惰…

rem基础+媒体查询+Less基础

一&#xff0c;rem基础 二&#xff0c;媒体查询 2.1什么是媒体查询 2.2语法规范 2.3媒体查询rem实现元素动态大小的变化 2.4 引入资源&#xff08;理解&#xff09; 三&#xff0c;Less基础 1 维护css的弊端 2 Less介绍 3 Less变量 变量命名规范 4 Less嵌套 5 Less…