委托、匿名函数与Lambda表达式初步
(以下内容主要来自《C#本质论第三版》第十二章委托和Lambda表达式)
一、委托续
上上周五看了看委托,初步明白了其是个什么,如何定义并调用。上周五准备看Lambda表达式,结果发现C#本质论中顺带讲了讲委托,所以在这,继续写一下委托。
首先,考虑如下问题:
需要对一个数组排序,先假设是数字,要求由大到小,很快我们便想到了冒泡排序
public static void bubblSort(int[] items)
{
int i, j, temp;
if (items == null)
{
throw new ArgumentNullException("错误");
}
for (i = items.Length - ; i >= ; i--)
{
for (j = ; j <= i; j++)
{
if (items[j - ]<items[j])
{
temp = items[j - ];
items[j - ] = items[j];
items[j] = temp;
}
}
}
}
显然,可以从大到小对数组进行排序,但是此时,我们要求对数组从大到小或者从小到大选择,也很简单,多写一个Switch就行了,如下:
public static void bubblSort(int[] items, string style )
{
int i, j, temp;
if (items == null)
{
throw new ArgumentNullException("错误");
}
for (i = items.Length - ; i >= ; i--)
{
for (j = ; j <= i; j++)
{
switch(style)
{
case "big":
if (items[j - ]<items[j])
{
temp = items[j - ];
items[j - ] = items[j];
items[j] = temp;
}
break;
case "little":
if (tems[j - ]<items[j])
{
temp = items[j - ];
items[j - ] = items[j];
items[j] = temp;
}
}
}
}
}
如此,我要是传入一串字符数组,然后按拼音排序呢,可以继续写Case语句,但是很明显,这样下去代码很臃肿。经过分析发现,关键就在于If语句里面的那个条件,如果我能将这个条件作为一个可变的就好了。
而具体判断呢,我可以写成一个一个的函数,到时候把这个函数传进来就行了,于是想到了委托,我可以定义一个如下类型的委托:
public delegate bool ComparisonHandler(int first, int second);
这样,通过控制何时返回真,便可以选择想要的排序类型了。
例如控制由大到小排序的函数如下:
public static bool LessTan(int first, int second)//将他传入委托,那么就是降序排序
{
return first < second;
}
BubbleSort函数改成如下形式:
public static void bubblSort(int[] items, ComparisonHandler comparisonhandler)
{
int i, j, temp;
if (items == null)
{
throw new ArgumentNullException("comparisonhandler");
}
for (i = items.Length - ; i >= ; i--)
{
for (j = ; j <= i; j++)
{
if (comparisonhandler(items[j - ], items[j]))//即判断是大是小以及判断规则,均有此委托指定,只要保证返回的bool类型符合规定即可
{
temp = items[j - ];
items[j - ] = items[j];
items[j] = temp;
}
}
}
}
可以看出,BubbleSort函数第二个参数是刚才定义的委托类型,那么当做如下调用的时候:
bubblSort(items,LessTan);
if语句会根据LessTan函数的返回值判断是否执行。当更改了LessTan函数体中的返回值的条件时(或者编写新的判断返回值的函数),便可以选择不同的排序方式了。
注:.net2.0以后,委托作为参数传入可以直接用相同签名的函数作为实参,而不需要实例化,实例化如下写:
bubblSort(items,new ComparisonHanlder(LessTan));
现在已经不需要这种写法。
二、匿名方法
我们由上文可知,BubbleSort接受了一个委托类型(实参为与委托有相同签名的函数),其实可以不写一个函数,而将LessTan写成如下形式:
//降序,我没有用委托调用LessThan,而是使用了匿名方法,当然在有参但是功能里不要参数的时候,可以省略参数列表,但是不推荐。
bubblSort(items, delegate(int first, int second) { return first < second; });
直接定义委托类型(这样说欠妥),而不写出任何名字,直接写参数列表与函数体,这样也可以传入BubbleSort,这就是一般的匿名函数的写法。
匿名函数的参数与返回值也要与其对应的委托类型一致。
当然,在一些情况下可以把参数省略:
//降序,我没有用委托调用LessThan,而是使用了匿名方法,当然在有参但是功能里不要参数的时候,可以省略参数列表,但是不推荐。
bubblSort(items, delegate{ return Console.WriteLine("!!"));
这样系统会自动匹配参数,但是特别不推荐这种写法。
三、Lambda表达式
Lambda表达式是C#3.0引进的 比匿名方法更加简洁的一种匿名函数语法,我可以不写Delegate了。但是要写看起来高大上的=>了。
例如匿名函数改成如下代码:
//语句Lambda
//还可以用Lambda表达式书写更加简介的匿名函数
bubblSort(items, (int first, int second) => { return first < second; });
可以这么读这句话:first与second用于返回比较结果。 这一组语句叫做 语句Lambda,传入Delegate类型的委托形参中,注意,变量与返回值要一致。
Lambda甚至可以允许省略参数类型,只要你确保编译器能够推断出来类型,所以以上语句可以改写如下:
//Lambda还可以推断类型,因为我定义的comparisonhandler的两个参数是int类型,所以可以不再写出类型,如果一个参数写出了类型,剩下的也要都写
bubblSort(items, (first, second) => { compareCount++; return first < second; });
注意,即使没有参数,Lambda表达式的左侧也要写()
刚才那种写法带大括号,属于语句Lambda。表达式Lambda只有一个表达式,写法如下:
//表达式Lambda写法
bubblSort(items, (first, second) => first < second);//语句有大括号组成的语句块,而表达式在右侧只有一个表达式
还有,当在表达式中调用外部变量的时候,我个人感觉他被在执行的时候当作了静态变量,例如上上句的compareCount是在主函数中定义的一个int类型,在Lambda表达式中调用了,在匿名函数的委托被销毁前,该外部变量将一直存在,所以会统计出实际的比较次数。
委托、匿名函数与Lambda表达式初步的更多相关文章
- 3 委托、匿名函数、lambda表达式
委托.匿名函数.lambda表达式 在 2.0 之前的 C# 版本中,声明委托的唯一方法是使用命名方法.C# 2.0 引入了匿名方法,而在 C# 3.0 及更高版本中,Lambda 表达式取代了匿名方 ...
- [C#学习教程-委托]001.大道至简之委托(代理),匿名函数,Lambda表达式
引言:此文翻译自CodeProject上的同名文章<C# Delegates,Anonymous Methods, and Lambda Expressions>,在此一起Mark一下,此 ...
- 匿名函数:Lambda表达式和匿名方法
匿名函数一个"内联"语句或表达式,可在需要委托类型的任何地方使用.可以使用匿名函数来初始化命名委托,或传递命名委托(而不是命名委托类型)作为方法参数. 共有两种匿名函数: Lamb ...
- C#语法之匿名函数和Lambda表达式
上一篇博客主要是对委托和事件做了一小结,这篇是在上一篇博客的基础上对匿名函数和Lambda表达式小结.还是接着上一篇说起,在上一篇中也说了委托是一种数据结构,主要是解决让函数作为参数的问题.在使用委托 ...
- 浅析匿名函数、lambda表达式、闭包(closure)区别与作用
浅析匿名函数.lambda表达式.闭包(closure)区别与作用 所有的主流编程语言都对函数式编程有支持,比如c++11.python和java中有lambda表达式.lua和JavaScript中 ...
- 测开之路八十二:匿名函数:lambda表达式
# 匿名函数:lambda表达式# lambda 参数: 逻辑f = lambda name: print(name)f('tom') f2 = lambda x, y: x + yprint(f2( ...
- 委托,匿名函数和lambda表达式
很早之前就接触到了委托,但是一直对他用的不是太多,主要是本人是菜鸟,能写的比较高级的代码确实不多,但是最近在看MSDN微软的类库的时候,发现了微软的类库好多都用到了委托,于是决定好好的研究研究,加深一 ...
- C++的匿名函数(lambda表达式)
总述 C++11提供了对匿名函数的支持,称为Lambda函数(也叫Lambda表达式). 它是定义和使用匿名函数对象的一种简便的方式.匿名函数是我们需要用到的一个函数,但是又不想去费力命名一个函数的 ...
- 匿名函数、lambda表达式
匿名函数 func = lambda x: y #x是形参,y是返回值 键字lambda表示匿名函数,冒号前面的x表示函数参数,冒号后面的y表示匿名函数的返回值. 例1:返回列表中长度大于等于3的元素 ...
随机推荐
- What is Split Brain in Oracle Clusterware and Real Application Cluster (文档 ID 1425586.1)
In this Document Purpose Scope Details 1. Clusterware layer 2. Real Application Cluster (d ...
- [转载]python中multiprocessing.pool函数介绍
原文地址:http://blog.sina.com.cn/s/blog_5fa432b40101kwpi.html 作者:龙峰 摘自:http://hi.baidu.com/xjtukanif/blo ...
- CODESOFT 2015中的二维码该怎样生成
由于二维条码具有储存量大.保密性高.追踪性高.抗损性强.备援性大.成本便宜等特性,其应用 渐趋广泛,因此二维码的制作对于CODESOFT条码设计软件的用户来讲可谓司空见惯.我们最常见的二维码要数QR码 ...
- THE ONE THING PEOPLE WILL MASSIVELY OVERPAY FOR (有一个东西人们是愿意出高价购买的)
THE ONE THING PEOPLE WILL MASSIVELY OVERPAY FOR有一个东西人们是愿意出高价购买的 by GARY VAYNERCHUK 点此直达湾区日报简评 I don' ...
- 将U盘分成 启动盘+文件存储区
我看了很多帖子,发现想要将U盘分区的朋友绝大部分是和我一样,想用U盘做成一个启动盘同时兼顾文件存储,分区的目的很简单,就是想将启动部分单独做成一个区,以免在日常的应用中使得启动文件染毒或者误操作造成损 ...
- oracle 删除表、表空间、用户时,如何释放磁盘空间
truncate table tablename DROP STORAGE; drop 执行drop table xx 语句drop后的表被放在回收站(user_recyclebin)里,而不是直接删 ...
- Scrapy安装、爬虫入门教程、爬虫实例(豆瓣电影爬虫)
Scrapy在window上的安装教程见下面的链接:Scrapy安装教程 上述安装教程已实践,可行.(本来打算在ubuntu上安装Scrapy的,但是Ubuntu 磁盘空间太少了,还没扩展磁盘空间,所 ...
- oracle表中某个字段含有字符回车、空格的手动修改方式
select t.*, t.rowid from TB_SD_STANDARD_CHOOSE_ADVISE t where t.id =323900000 update TB_SD_STANDARD_ ...
- LINE最新版6.5.0在iOS上的删除信息取证
iOS: 9.3.2版 LINE: 6.5.0版 取出LINE的数据库 Line.sqlite,路径如下所示: 检视删除的信息,发现还有不少残留,虽然都是片段,但拼拼凑凑总还是能有些蛛丝马迹,毕竟,总 ...
- 查找Safari相关迹证
日前有取证的同好提及Safari,想了解详细步骤,因而在此再补充说明相关. 除了Winodws外,Mac OS X也有为数不少的使用者,以下便以OS X自带的Safari浏览器为例,来查看有哪些重要迹 ...