当前位置: 首页 > news >正文

C#3.0入门系列(四)

Lambda表达式中Lifting

Lambda表达式是由匿名方法演化而来的更加高级的形式。关于匿名方法,请参阅http://msdn.microsoft.com/msdnmag/issues/04/05/C20/。关于Lambda表达式的演化,请参阅http://msdn.microsoft.com/msdnmag/issues/07/06/csharp30/default.aspx?loc=zh。英文原版为http://msdn.microsoft.com/msdnmag/issues/07/06/CSharp30/

1,Lambda表达式中的lifting
在c# 2.0中,匿名方法的使用,是这样的。

class SomeClass
{
delegatevoidSomeDelegate();
publicvoidInvokeMethod()
{
SomeDelegatedel
=delegate()
{
MessageBox.Show(
"Hello");
}
;
del();
}

}


在LINQ 的演变及其对 C# 设计的影响 一文中,其断言如果 lambda 表达式首先被引入语言,那么就不会有对匿名方法的需要了。在本系列前面的一些文章中,也曾提到lambda 表达式,但并没有做太深入的引述。本文所要讲的是Lambda表达式中lifting,将开始和大家体会lambda表达式的一些细节。

编译下面的小程序,看看输出结果,是不是大吃一惊
using System;
using System.Collections.Generic;
using System.Linq;

namespace Tester
{
classProgram
{
staticvoidMain(string[]args)
{
List
<Func<int>>list=newList<Func<int>>();

for(inti=0;i<3;i++)
{
list.Add(()
=>i);
}


foreach(variteminlist)
{
Console.WriteLine(item());
}

}

}

}

我们定义了一个list,其存储格式为func<int>,即返回int型的代理。而后,用for循环,将 i 封装进lambda表达式,并加入到该list中。而后,用foreach循环输出结果。因为lambda表达式,其实质就是个代理,也就指向一个匿名函数,所以,使用item()来调用它,让所指向的函数执行。

问题是,你所盼望输出,0,1,2,而实际结果均是3。为什么会这样呢?这牵扯到两个原因。
第一,在for循环中,只能有一个 i 变量。即再第一次循环时,i 的地址就分配好了,不会因为循环次数的多少而发生任何改变,其改变的只能是里面装载的值。

第二,lambda表达式在构造时, 传进去的是变量的地址,而不是具体值。只有当真正执行这个lambda表达式时,才会去确定它的值。这就是为什么上面的例子中,其结果均为3。(for循环在最后,又给 i 加了1)

我们可以很容易,就将起解决掉。在for循环中,定义一临时变量,存储 i 的值即可。因为编译器会对该临时变量重新分配内存,这样,每次循环,都重新分配新的内存,就不会有这个问题了。再来运行下面的这个例子。
using System;
using System.Collections.Generic;
using System.Linq;

namespace EnterpriseTester
{
classProgram
{
staticvoidMain(string[]args)
{
List
<Func<int>>list=newList<Func<int>>();

for(inti=0;i<3;i++)
{
inttemp=i;
list.Add(()
=>temp);
}


foreach(variteminlist)
{
Console.WriteLine(item());
}

}

}

}
是不是满足了你的要求了呢?这个temp,就称为lifting。lift是美语中的电梯,翻译为梯子或垫脚石,比较妥帖。

2,lifting在Linq To Sql中的影响。
Lambda表达式在Linq To Sql中大量应用,这个问题势必要影响到其sql语句的形成。看下面的例子
string []keyWords = string []keyWords = new string [] {"111","222","333","444"} ;
SomeDataContextctx
= new SomeDataContext();
varentitys
= frome in ctx.Entity
selecte;
foreach ( string keyWord in keyWords)
{
entitys
=entitys.Where(e=>e.Text.Contains(keyWord));
}
var q = entitys.ToList();
本意是想查找,全部满足模糊匹配的所有记录,其实际生成的sql语句中,只传入了“%444%”。加个lifting吧,问题就解决了。
大家可以用for循环替换foreach循环,如果,不加lifting,是不是抛异常了呢?自己研究下原因哦。

相关文章:

  • GCC 的简单使用
  • 关于Keil 的一些看法
  • Jackson 简单使用记录
  • java基础设计 开源框架
  • Spring源码学习笔记
  • 正则资料笔记
  • C#接口慨述
  • Inversion of Control 简要笔记
  • 定义接口及定义接口成员
  • 小马哥讲Spring核心编程思想 - 第二章 重新认识IoC
  • 访问接口
  • 记录一次 post 请求的并发测试
  • RPC与 Dubbo 资料梳理
  • 实现接口
  • dubbo 常见用法与配置梳理(一)
  • [LeetCode] Wiggle Sort
  • [nginx文档翻译系列] 控制nginx
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • 345-反转字符串中的元音字母
  • C++类中的特殊成员函数
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • echarts花样作死的坑
  • es6(二):字符串的扩展
  • iOS 系统授权开发
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • Javascript编码规范
  • Netty 4.1 源代码学习:线程模型
  • PHP的类修饰符与访问修饰符
  • sessionStorage和localStorage
  • 诡异!React stopPropagation失灵
  • 技术:超级实用的电脑小技巧
  • 利用DataURL技术在网页上显示图片
  • 你真的知道 == 和 equals 的区别吗?
  • 如何设计一个微型分布式架构?
  • 实现菜单下拉伸展折叠效果demo
  • 算法-插入排序
  • ​如何在iOS手机上查看应用日志
  • (1)(1.11) SiK Radio v2(一)
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (BFS)hdoj2377-Bus Pass
  • (MATLAB)第五章-矩阵运算
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (三)uboot源码分析
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • (转)利用ant在Mac 下自动化打包签名Android程序
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .NET CLR Hosting 简介
  • .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调