转 拉姆达表达式,委托、匿名方法、Lambda表达式的演进
总结:Lambda表达式的语法:(参数列表=>执行语句)
无参数格式 :()=>{执行语句}
有参数格式:x=> x % 2 == 0
1、假设给我们一个泛型对象List<T>,T为int类型,要求我们使用该对象方法FindAll(Predicate<T> match)从中找出该List中的偶数,您如何实现?
说明一下:Predicate<T>是一个泛型委托,它的原型为public delegate bool Predicate<T>(T obj),该委托传入一个T类型对象,经逻辑判断后返回布尔值。
委托
可能您首先想到的是用委托实现,实现方法如下:
// 方法1
static void Method1()
{
// 创建List<int>对象
List < int > list = new List < int > ();
list.AddRange( new int [] { 1 , 2 , 3 , 4 , 5 , 6 }); // 定义一个委托
Predicate < int > callback = new Predicate < int > (IsEvenNumber);
// 执行FindAll方法,该方法使用传入的委托callback来判断列表中的整数是否为偶数
List < int > evenNumbers = list.FindAll(callback); // 输出
foreach ( int i in evenNumbers)
{
Console.Write( " {0: 0} " , i);
} Console.WriteLine();
} // 判断传入的整数是否为偶数
static bool IsEvenNumber( int i)
{
return i % 2 == 0 ;
}
复制代码
这个方法不错,简单、直观,就是有些......,有些什么?代码显得有些累赘,我们仅仅是要执行“i % 2 == 0”这样一个判断语句,却要为这一条语句专门定义一个方法和一个委托。如果该方法在别处根本未被使用,那有没有什么办法省去它呢(当然不是真正的省去,编译后,该方法其实还存在,我们的目的是至少不用让咱们特意为这条语句输入一个方法和一个委托)?这时,我们的匿名方法该登场啦!
匿名方法
看下面的代码:
static void Method2()
{
// 创建List<int>对象
List < int > list = new List < int > ();
list.AddRange( new int [] { 1 , 2 , 3 , 4 , 5 , 6 }); // 创建匿名方法,并将其传给FindAll方法
List < int > evenNumbers = list.FindAll
(
delegate ( int i)
{
return i % 2 == 0 ;
}
); // 输出
foreach ( int i in evenNumbers)
{
Console.Write( " {0: 0} " , i);
} Console.WriteLine();
}
复制代码
上例中delegate ( int i) { return i % 2 == 0 ; }语句创建了一个内联匿名方法的委托,并传给FindAll用于判断列表中的一个整数是否为偶数。相较于Method1,我们不用特意定义一个方法和一个委托,代码是精减了不少,但看着是不是有些别扭?这个匿名方法的原型是啥样?
么急,一点点来分析。(int i)就是咱们定义的匿名方法的参数列表,return后返回一个布尔值,这就是该方法的返回值,这么看来,咱们的内联匿名方法的委托原型其实就是:
delegate bool 匿名(int i)
看起来眼熟啊!这不和Predicate<T>的原型public delegate bool Predicate<T>(T obj),T代入int类型后一样嘛!耶,真巧啊!是啊,不巧不行啊,您定义的匿名方法原型如果不是这个样的话,那编译器就直接报错啦!List<int>.FindAll方法可是要求传入一个Predicate<T>的委托呢!
嗯,这么说来,内联匿名方法的委托定义语法是这个样啦:
delegate (参数列表)
{
执行语句
}
复制代码
Lambda表达式
匿名方法的实现已经够简练了,还有啥更简练的语法来实现么?啥?还要简练?匿名方法的语法就够晕乎了,还要咋个简练法,有些BT吧!么办法,微软就是这么BT。咱们就来看看更BT的Lambda表达式吧。小二,上代码:
static void Method3()
{
// 创建List<int>对象
List < int > list = new List < int > ();
list.AddRange( new int [] { 1 , 2 , 3 , 4 , 5 , 6 }); // 创建Lambda表达式并传给FindAll方法
List < int > evenNumbers = list.FindAll
(
( int x) => { return x % 2 == 0 ; } // 注意这里噢,这就是大名鼎鼎的Lambda表达式
); // 输出
foreach ( int i in evenNumbers)
{
Console.Write( " {0: 0} " , i);
} Console.WriteLine();
}
复制代码
看到这行代码了吧:(int x) => { return x % 2 == 0; }
这是个啥东西?Lambda表达式?对头!
让我们来分析一下Lambda表达式的语法:别的先不管,关注一下“=>”符号。Lambda表达式被该符号分为两部分,符号的前半部分是参数列表,后半部分是执行语句,简化一下就是这样:
参数列表=>执行语句
眼熟不?嗯,好像、大概、似乎、肯定、因为、所以有点眼熟,对了,这结构不和匿名方法一个样吗?咱再回头看看匿名方法的语法:
delegate(参数列表){执行语句}
看出来了吧,Lambda表达式就是匿名方法嘛!区别仅在于用“=>”符号隔开了参数列表和执行语句而已。这么说来,语句(int x) => { return x % 2 == 0; }不过是为FindAll传入了一个内联匿名方法的委托,该方法的参数列表为(int x),返回一个布尔值。
至此,是不是值得庆祝一下?我们好像开始理解这个BT的Lambda表达式了,现在应该叫小二上二锅头了吧,我再也不想看这让人晕乎的代码了。不过,先别高兴,微软又说了,这还不是最简练的!啥?这还不简练?那你写一个更简练的看看?小二,再上一盘代码:
static void Method4()
{
// 创建List<int>对象
List < int > list = new List < int > ();
list.AddRange( new int [] { 1 , 2 , 3 , 4 , 5 , 6 }); // 创建Lambda表达式并传给FindAll方法
List < int > evenNumbers = list.FindAll
(
x => x % 2 == 0 // 看到这里,是不是有些无语了
); // 输出
foreach ( int i in evenNumbers)
{
Console.Write( " {0: 0} " , i);
} Console.WriteLine();
}
复制代码
?看看这个:
x=> x % 2 == 0
这是我们第二次看到Lambda表达式了,只要记着Lambda表达式的语法:(参数列表=>执行语句)就行了。x就是该式的参数列表,为啥x连个参数类型都没有呢?因为编译器知道咱们要传入的方法原型是bool Predicate<int>(int obj),自动就认为参数x的类型为int类型。同理,编译器也知道方法的返回值为布尔型,执行语句(x % 2 == 0)就是一个布尔型表达式,所以,编译器也认为咱们要返回的就是这个表达式了。最后Lambda表达式就像被扒光了衣服的小正太一样,裸奔在咱们的代码中了。嗯,很好,裸一裸更健康!
咱们的委托、匿名方法、Lambda表达式的演进之旅这样结束了。不过,好像还有一个问题,如果咱们的匿名方法不带参数,那Lambda应该怎么写?嗯,先别说答案,让我想想,是不是这样“()=>{执行语句}”?对啦,就是这样!
刚接触这种BT的Lambda表达式,真是有些讨厌,这语法简练到“祼奔”了,但时间长了,你会发现它实在是太强大了,你一定会爱上这BT的Lambda表达式的。
class Program
{
static void Main(string[] args)
{
List<int> list = new List<int>() { , , , , , , };
List<Searchfile> lstf = new List<Searchfile>();
for (int i = ; i < ; i++)
{
Searchfile model = new Searchfile();
DateTime dt = System.DateTime.Now;
model.CreatTime = dt.AddMinutes(i);
model.FileFullName = i.ToString();
lstf.Add(model);
} lstf = lstf.FindAll(w => w.CreatTime > DateTime.Now); IEnumerable<Searchfile> query = lstf.FindAll(w => w.CreatTime > DateTime.Now).OrderBy(f => f.CreatTime); OrderByEx1();
Console.ReadLine();
} //orderby
public static void OrderByEx1()
{
Pet[] pets = { new Pet { Name="Barley", Age= },
new Pet { Name="Boots", Age= },
new Pet { Name="Whiskers", Age= } }; IEnumerable<Pet> query = pets.OrderBy(pet => pet.Age);
foreach (Pet pet in query)
{
Console.WriteLine("{0} - {1}", pet.Name, pet.Age);
}
}
} public class Searchfile
{
public string FileFullName { get; set; }
public string FileShortName { get; set; }
public DateTime CreatTime { get; set; }
public long FileSpace { get; set; } } class Pet
{
public string Name { get; set; }
public int Age { get; set; }
}
转 拉姆达表达式,委托、匿名方法、Lambda表达式的演进的更多相关文章
- 委托-异步调用-泛型委托-匿名方法-Lambda表达式-事件【转】
		
1. 委托 From: http://www.cnblogs.com/daxnet/archive/2008/11/08/1687014.html 类是对象的抽象,而委托则可以看成是函数的抽象.一个委 ...
 - C#多线程+委托+匿名方法+Lambda表达式
		
线程 下面是百度写的: 定义英文:Thread每个正在系统上运行的程序都是一个进程.每个进程包含一到多个线程.进程也可能是整个程序或者是部分程序的动态执行.线程是一组指令的集合,或者是程序的特殊段,它 ...
 - C# delegate event func action 匿名方法 lambda表达式
		
delegate event action func 匿名方法 lambda表达式 delegate类似c++的函数指针,但是是类型安全的,可以指向多个函数, public delegate void ...
 - 委托delegate    泛型委托action<>    返回值泛型委托Func<>   匿名方法    lambda表达式 的理解
		
1.使用简单委托 namespace 简单委托 { class Program { //委托方法签名 delegate void MyBookDel(int a); //定义委托 static MyB ...
 - 18、(番外)匿名方法+lambda表达式
		
概念了解: 1.什么是匿名委托(匿名方法的简单介绍.为什么要用匿名方法) 2.匿名方法的[拉姆达表达式]方法定义 3.匿名方法的调用(匿名方法的参数传递.使用过程中需要注意什么) 什么是匿名方法? 匿 ...
 - 匿名函数 =匿名方法+ lambda 表达式
		
匿名函数的定义和用途 匿名函数是一个"内联"语句或表达式,可在需要委托类型的任何地方使用. 可以使用匿名函数来初始化命名委托[无需取名字的委托],或传递命名委托(而不是命名委托类型 ...
 - C#委托总结-匿名方法&Lambda表达式
		
1,匿名方法 匿名方法可以在声明委托变量时初始化表达式,语法如下 之前写过这么一段代码: delegate void MyDel(string value); class Program { void ...
 - (28)C#委托,匿名函数,lambda表达式,事件
		
一.委托 委托是一种用于封装命名和匿名方法的引用类型. 把方法当参数,传给另一个方法(这么说好理解,但实际上方法不能当参数,传入的是委托类型),委托是一种引用类型,委托里包含很多方法的引用 创建的方法 ...
 - 匿名函数:Lambda表达式和匿名方法
		
匿名函数一个"内联"语句或表达式,可在需要委托类型的任何地方使用.可以使用匿名函数来初始化命名委托,或传递命名委托(而不是命名委托类型)作为方法参数. 共有两种匿名函数: Lamb ...
 - 委托学习过程及委托、Lambda表达式和匿名方法的关系总结及事件总结
		
第一章,当开始学习委托的时候,我们会问什么是委托?为什么要学习委托? 一,什么是委托? 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法, ...
 
随机推荐
- Python基础-迭代器&生成器&装饰器
			
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 我现在有个需求,看 ...
 - hdu 5142(数学-进制转换)
			
NPY and FFT Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
 - C/C++/C#程序如何打成DLL动态库
			
C/C++程序如何打成DLL动态库:1.在VS中新建main.h,添加如下内容:extern "C" _declspec(dllexport) int onLoad(); 2.新建 ...
 - 使用Android Studio开发调用.NET Webservice 之初体验
			
本人是.NET出身 但苦于领导要让研究Android 外壳然后准备套html5 ,当试验兵真坑啊 但也没办法 咱还得研究啊,索性 不辜负领导的期望(也研究好两三天了)总算弄明白了 app本地存储 和 ...
 - AC日记——Roma and Poker codeforces 803e
			
803E - Roma and Poker 思路: 赢或输或者平的序列: 赢和平的差的绝对值不得超过k: 结束时差的绝对值必须为k: 当“?”时可以自己决定为什么状态: 输出最终序列或者NO: dp( ...
 - Python与数据库[2] -> 关系对象映射/ORM[3] -> sqlalchemy 的声明层 ORM 访问方式
			
sqlalchemy的声明层ORM访问方式 sqlalchemy中可以利用声明层进行表格类的建立,并利用ORM对象进行数据库的操作及访问,另一种方式为显式的 ORM 访问方式. 主要的建立步骤包括: ...
 - zzc种田
			
题目背景 可能以后 zzc就去种田了. 题目描述 田地是一个巨大的矩形,然而zzc 每次只能种一个正方形,而每种一个正方形时zzc所花的体力值是正方形的周长,种过的田不可以再种,zzc很懒还要节约体力 ...
 - [POI2014]Supercomputer
			
题目大意: 给定一个$n(n\le10^6)$个结点的有根树,从根结点开始染色.每次可以染和已染色结点相邻的任意$k$个结点.$q(q\le10^6)$组询问,每次给定$k$,问至少需要染几次? 思路 ...
 - Android开发之onCreate
			
最近看了一些开发人员做的APP开发,虽然都实现了比较完美的功能,不过很多地方很是牵强!我觉得:作为一个合格软件工程师,最重要的不是你写过多少代码,而是你研究过多少代码!所以,我更倡导多研究系统原本定制 ...
 - 【hibernate/JPA】对实体类的的多个字段建立唯一索引,达到复合主键的效果【spring boot】注解创建唯一索引和普通索引
			
对实体类的的多个字段建立唯一索引,达到复合主键的效果 package com.sxd.swapping.domain; import lombok.Getter; import lombok.Sett ...