谷歌广告开户婚纱摄影网站应该如何做优化
2026/4/18 9:13:11 网站建设 项目流程
谷歌广告开户,婚纱摄影网站应该如何做优化,广东网站制作多少钱,这么建立com的网站一、Lambda 表达式的演变史#xff1a;从 “繁” 到 “简” 的语法进化 Lambda 表达式不是凭空出现的#xff0c;它是.NET 为了简化 “委托实例化” 写法而逐步优化的结果。我们以 “筛选整数列表中大于 5 的数” 为例#xff0c;看完整的演变过程#xff1a; 阶段 1#…一、Lambda 表达式的演变史从 “繁” 到 “简” 的语法进化Lambda 表达式不是凭空出现的它是.NET 为了简化 “委托实例化” 写法而逐步优化的结果。我们以 “筛选整数列表中大于 5 的数” 为例看完整的演变过程阶段 1原始委托.NET 1.0—— 最繁琐的写法假设你在 2002 年.NET 1.0 刚发布开发电商后台需要从订单列表中筛选出 “金额大于 1000 元的订单”。当时.NET 只有原始委托机制没有简化写法你必须按 “定义委托→写命名方法→实例化委托” 的步骤实现。// 1. 定义订单实体模拟业务数据publicclassOrder{publicintOrderId{get;set;}publicdecimalAmount{get;set;}// 订单金额publicstringCustomer{get;set;}}// 2. 定义匹配筛选逻辑的委托类型输入Order返回boolpublicdelegateboolOrderFilterDelegate(Orderorder);classProgram{staticvoidMain(){// 模拟数据库查询出的订单列表ListOrderordersnewListOrder{newOrder{OrderId1,Amount800,Customer张三},newOrder{OrderId2,Amount1200,Customer李四},newOrder{OrderId3,Amount1500,Customer王五}};// 3. 编写具体的筛选方法匹配委托签名boolFilterHighAmountOrder(Orderorder){returnorder.Amount1000;// 核心筛选逻辑金额1000}// 4. 实例化委托并传入筛选方法OrderFilterDelegatefilterFilterHighAmountOrder;foreach(varorderinorders){if(filter.Invoke(order)){Console.WriteLine(${order.OrderId}{order.Customer}的金额为{order.Amount},大于1000);}}}}核心问题在这个例子中我们先定义了筛选方法吗再将筛选方法传入委托这个过程其实有点繁琐能不能去掉定义筛选方法这一步呢直接在注册委托时传入背景事件.NET 2.0 时代简化订单筛选的写法到了 2005 年.NET 2.0 发布你觉得原始委托的命名方法太冗余想直接在使用委托的地方写筛选逻辑避免定义多余的命名方法。此时匿名方法登场解决了这个痛点。usingSystem;usingSystem.Collections.Generic;publicclassOrder{publicintOrderId{get;set;}publicdecimalAmount{get;set;}publicstringCustomer{get;set;}}// 依然保留委托类型新手需要先理解委托的本质publicdelegateboolOrderFilterDelegate(Orderorder);classProgram{staticvoidMain(){ListOrderallOrdersnewListOrder{newOrder{OrderId1,Amount800,Customer张三},newOrder{OrderId2,Amount1200,Customer李四},newOrder{OrderId3,Amount1500,Customer王五}};// 关键优化直接用匿名方法实例化委托省去命名方法OrderFilterDelegatefilterMethoddelegate(Orderorder){// 核心筛选逻辑直接写在这里不用单独定义方法returnorder.Amount1000;};// 依然用纯手动循环筛选无LINQ/FindAllListOrderhighAmountOrdersnewListOrder();foreach(OrderorderinallOrders){if(filterMethod(order)){highAmountOrders.Add(order);}}Console.WriteLine(金额大于1000的订单);foreach(varorderinhighAmountOrders){Console.WriteLine($订单ID{order.OrderId}金额{order.Amount}客户{order.Customer});}}}核心解析给新手的话匿名方法就是 “没有名字的方法”直接写在委托实例化的位置少了 “定义命名方法” 这一步但delegate关键字、括号、大括号还是有点繁琐尤其是逻辑只有一行时显得没必要。背景事件.NET 3.5追求极致简洁的筛选写法你作为新手希望把筛选逻辑写成 “一眼就能看懂” 的极简形式不用多余的关键字 ——Lambda 表达式就是匿名方法的 “终极简化版”。usingSystem;usingSystem.Collections.Generic;publicclassOrder{publicintOrderId{get;set;}publicdecimalAmount{get;set;}publicstringCustomer{get;set;}}// 委托类型依然保留新手需要知道Lambda的底层还是委托publicdelegateboolOrderFilterDelegate(Orderorder);classProgram{staticvoidMain(){ListOrderallOrdersnewListOrder{newOrder{OrderId1,Amount800,Customer张三},newOrder{OrderId2,Amount1200,Customer李四},newOrder{OrderId3,Amount1500,Customer王五}};// 关键Lambda表达式替代匿名方法极致简化// 格式参数 逻辑箭头读作“输入...返回...”OrderFilterDelegatefilterMethodorderorder.Amount1000;// 纯手动循环筛选无任何LINQ相关ListOrderhighAmountOrdersnewListOrder();foreach(OrderorderinallOrders){if(filterMethod(order)){highAmountOrders.Add(order);}}Console.WriteLine(金额大于1000的订单);foreach(varorderinhighAmountOrders){Console.WriteLine($订单ID{order.OrderId}金额{order.Amount}客户{order.Customer});}}}补充Lambda 的语法规则场景Lambda 写法示例说明无参数() Console.WriteLine(Hi)空括号表示无参数单参数num num 5单参数可省略括号多参数(a, b) a b多参数必须加括号多行逻辑(a, b) { var sum a b; return sum; }大括号包裹多行需显式 return核心解析给新手的话Lambda 表达式order order.Amount 1000完全等价于之前的命名方法 / 匿名方法只是写法更简单箭头左边是 “输入的参数”右边是 “要执行的逻辑”新手可以理解为 “给我一个 order我返回它的金额是否大于 1000”。二、Lambda 的底层本质为什么同样的写法有不同行为背景事件新手的困惑 —— 同样的 Lambda为啥有的能直接执行有的能 “拆开来分析”你作为新手发现同样的 Lambda 写法赋值给不同的变量类型行为完全不同一种能直接执行另一种能 “拆开来看到内部逻辑”。我们用纯基础语法演示这个差异。usingSystem;usingSystem.Collections.Generic;usingSystem.Linq.Expressions;publicclassOrder{publicintOrderId{get;set;}publicdecimalAmount{get;set;}}classProgram{staticvoidMain(){ListOrderallOrdersnewListOrder{newOrder{OrderId1,Amount800},newOrder{OrderId2,Amount1200}};// 场景1Lambda赋值给委托类型能直接执行// 新手理解这是“可执行的Lambda”底层是编译好的代码FuncOrder,boolexecutableLambdaorderorder.Amount1000;// 手动循环执行纯基础语法ListOrderresult1newListOrder();foreach(varorderinallOrders){if(executableLambda(order))// 直接调用执行{result1.Add(order);}}Console.WriteLine(可执行Lambda的筛选结果数result1.Count);// 输出1// 场景2Lambda赋值给表达式树类型能解析逻辑// 新手理解这是“可分析的Lambda”底层是描述逻辑的“结构图”ExpressionFuncOrder,boolanalyzableLambdaorderorder.Amount1000;// 解析表达式树新手先知道“能看内部逻辑”即可Console.WriteLine(\n解析Lambda的内部逻辑);ParameterExpressionparam(ParameterExpression)analyzableLambda.Parameters[0];BinaryExpressionbody(BinaryExpression)analyzableLambda.Body;Console.WriteLine($输入参数{param.Name}Order类型);Console.WriteLine($执行操作{body.NodeType}大于);Console.WriteLine($判断的字段{body.Left}订单金额);Console.WriteLine($判断的数值{body.Right}1000);// 表达式树要先编译成委托才能执行FuncOrder,boolcompiledLambdaanalyzableLambda.Compile();ListOrderresult2newListOrder();foreach(varorderinallOrders){if(compiledLambda(order)){result2.Add(order);}}Console.WriteLine(\n表达式树编译后筛选结果数result2.Count);// 输出1}}核心解析给新手的话Lambda 本身只是 “写起来方便的语法”不是新东西赋值给FuncOrder, bool委托变成 “能直接跑的代码”赋值给ExpressionFuncOrder, bool表达式树变成 “能拆开来分析的结构图”要先编译成委托才能执行。三、Lambda 与匿名类临时封装数据无反射 纯基础语法背景事件新手开发后台需要临时封装简化的用户数据你作为新手需要把用户的完整信息ID、姓名、年龄、城市转换成 “只包含姓名、年龄、地区” 的临时数据不想专门定义新类。这个场景下完全不用反射利用 C# 编译器的类型推导就能直接访问匿名类属性结合 Lambda 完成筛选和封装。usingSystem;usingSystem.Collections.Generic;classProgram{staticvoidMain(){// 模拟完整的用户数据直接定义匿名类列表编译器自动推导类型无需objectvarfullUsersnewListdynamic// 用dynamic让编译器兼容同结构匿名类{new{Id1,Name张三,Age25,City北京},new{Id2,Name李四,Age30,City上海},new{Id3,Name王五,Age22,City北京}};// 需求筛选出北京的用户并封装成只含“姓名、年龄、地区”的临时数据varsimplifiedUsersnewListdynamic();// 存储简化后的匿名类数据// 用Lambda封装筛选逻辑无反射直接访问匿名类属性// 新手理解这个Lambda的作用是“输入一个用户判断是否是北京用户”Funcdynamic,boolisBeijingUseruseruser.City北京;// 纯手动循环无LINQ执行筛选和封装foreach(varuserinfullUsers){// 调用Lambda判断是否是北京用户if(isBeijingUser(user)){// 匿名类临时封装简化数据不用定义新类// 直接访问原匿名类的Name/Age/City属性无任何反射varsimplifiedUsernew{姓名user.Name,// 直接取原数据的姓名年龄user.Age,// 直接取原数据的年龄地区$中国-{user.City}// 拼接地区信息};simplifiedUsers.Add(simplifiedUser);}}// 输出临时封装的数据直接访问新匿名类的属性无反射Console.WriteLine(北京用户的简化数据);foreach(varuserinsimplifiedUsers){Console.WriteLine($姓名{user.姓名}年龄{user.年龄}地区{user.地区});}}}输出结果北京用户的简化数据 姓名张三年龄25地区中国-北京 姓名王五年龄22地区中国-北京四、Lambda 与扩展方法给现有类型加功能纯基础语法背景事件新手想给 int 类型加 “判断偶数” 的方法扩展方法就像 “给手机贴定制手机壳”手机原有类型如int、string、自定义Order类的内部结构完全不变不用改源码也不用换手机不用创建子类贴了手机壳扩展方法后手机多了 “防摔、支架” 等新功能新增方法用的时候新功能看起来就像手机自带的调用方式和实例方法一样。扩展方法是 C# 的语法糖编译器层面的简化写法允许你在不修改原有类型源码的前提下不创建该类型子类的前提下给现有类型包括内置类型如int/string、自定义类、接口、密封类新增 “看起来像自带实例方法” 的功能。扩展方法有严格的语法约束少任何一条都无法生效我们先通过 “给 int 加判断偶数方法” 的基础示例拆解所有规则usingSystem;// 规则1扩展方法必须放在【静态类】中且类的访问级别要能被调用处访问如publicpublicstaticclassIntExtensions// 静态类名通常以“要扩展的类型Extensions”命名是约定俗成的规范{// 规则2扩展方法本身必须是【静态方法】// 规则3第一个参数必须用【this关键字】标记且参数类型要扩展的类型这里是int// 规则4第一个参数不能加ref/out修饰符publicstaticboolIsEven(thisintnum){// 只能访问int的公有成员规则5扩展方法无法访问原有类型的私有成员returnnum%20;}}classProgram{staticvoidMain(){intorderCount10;// 调用扩展方法看起来像int的“自带实例方法”boolresultorderCount.IsEven();Console.WriteLine($订单数量{orderCount}是否为偶数{result});}}扩展方法看起来是 “给类型加了新方法”但底层编译器只是把 “实例方法式的调用” 转换成了 “静态方法的调用”—— 没有任何底层新特性只是写法更友好。背景事件新手的疑惑 —— 扩展方法到底是不是 “真的加了方法”usingSystem;publicstaticclassIntExtensions{publicstaticboolIsEven(thisintnum){returnnum%20;}}classProgram{staticvoidMain(){intorderCount10;// 写法1扩展方法的“语法糖写法”新手看到的友好写法boolresult1orderCount.IsEven();// 写法2编译器实际编译后的写法本质是静态方法调用boolresult2IntExtensions.IsEven(orderCount);// 两种写法完全等价结果一致Console.WriteLine($语法糖写法结果{result1});Console.WriteLine($编译器实际写法结果{result2});}}输出语法糖写法结果True 编译器实际写法结果True核心解析给新手的话扩展方法的本质是静态方法的 “伪装”你写的orderCount.IsEven()编译器会自动转换成IntExtensions.IsEven(orderCount)原有类型如int的源码、内存结构完全没变只是调用静态方法的写法更像 “实例方法”这也是为什么扩展方法无法访问原有类型私有成员 —— 因为它本质是外部静态方法不是类型的内部方法。总结Lambda 的本质是委托 / 表达式树的 “简化写法”从原始委托→匿名方法→Lambda只是写法越来越简单底层都是新手能理解的 “方法 / 委托”核心规则Lambda 的行为由赋值的变量类型决定 —— 赋值给委托Func能直接执行赋值给表达式树Expression能解析逻辑基础用法结合匿名类可临时封装数据结合扩展方法可给现有类型加功能全程只用基础循环 / 方法调用不用提前学 LINQ。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询