转载 C#匿名函数 委托和Lambda表达式
转载原出处: http://blog.csdn.net/honantic/article/details/46331875
匿名函数
匿名函数(Anonymous Function)是表示“内联”方法定义的表达式。匿名函数本身及其内部没有值或者类型,但是可以转换为兼容的委托或者表达式树类型(了解详情)。匿名函数转换的计算取决于转换的目标类型:如果是委托类型,则转换计算为引用匿名函数所定义的方法的委托;如果是表达式树类型,则转换将计算以对象结构形式表示方法结构的表达式树。
匿名函数有两种语法风格:Lambda表达式(lambda-expression)和匿名方法表达式(anonymous-method-expression)。在几乎所有的情况下,Lambda表达式都比匿名方法表达式更为简介具有表现力。但现在C#语言中仍保留了后者,为了向后兼容。
Lambda表达式:
async可选 (匿名的函数签名)=> (匿名的函数体)
匿名方法表达式:
async可选 delegate (显式的匿名函数签名) 可选{代码块}
其中匿名的函数签名可以包括两种,一种是隐式的匿名函数签名另一种是显式的匿名函数签名:
隐式的函数签名:(p)、(p1,p1)
显式的函数签名:(int p)、(int p1,int p2)、(ref int p1,out int p2)
匿名的函数体可以是表达式或者代码块。
从上面我们可以看出,Lambda表达式的参数形式可以显式或者隐式类型化。在显式类型化参数列表中,每个参数的类型是显式声明的,在隐式类型化参数列表中,参数的类型是从匿名函数出现的上下文中推断出来的。
当Lambda表达式只有一个具有隐式类型化参数的时候,参数列表可以省略圆括号,也就是说:
(参数) => 表达式
可以简写为
参数 => 表达式
一些匿名函数的示例
x => x + 1 //隐式的类型化,函数体为表达式
x => {return x + 1;} //隐式的类型化,函数体为代码块
(int x) => x + 1 //显式的类型化,函数体为表达式
(int x) => {return x + 1;} //显式的类型化,函数体为代码块
(x , y) => x * y //多参数
() => Console.WriteLine() //无参数
async (t1 , t2) => await t1 + await t2 //异步
delegate (int x) {return x + 1;} //匿名函数方法表达式
delegate {return 1 + 1;} //参数列表省略
Lambda表达式和匿名方法表达式的区别:
● 当没有参数的时候,匿名方法表达式允许完全省略参数列表,从而可以转换为具有任意值参数列表的委托类型,Lambda表达式则不能省略参数列表的圆括号()。
● Lambda表达式允许省略和推断类型参数,而匿名方法表达式要求显式声明参数类型。
● Lambda表达式主体可以为表达式或者代码块,而匿名方法表达式的主体必须为代码块。
● 只有Lambda表达式可以兼容到表达式树类型。
委托
一个委托是一个指向一个方法的引用,或者说,一个委托的实例就是一个指向某个方法的对象,这是一个简单却十分强大的概念。
C#中的委托是用来处理在其他语言中(如C++、Pascal等)需要用函数指针来处理的情况。不过与C++不同的是:委托是完全面向对象的;C++指针仅仅指向成员函数,而委托同时封装了对象的实例和方法;委托是完全类型安全的,只有当函数的签名与委托的签名匹配的时候,委托才可以指向该方法,当委托没有合法的指向方法的时候不能被调用。
一些关于委托的知识点:
1.委托是类型安全的
委托类型的返回类型必须为void或者输出安全,委托类型的所有形参类型都必须是输入安全的。
2.委托类型是名称等效,不是结构等效
也就是说,对于两个委托类型,即使它们具有相同的参数列表和返回类型,它们仍将被视为两个不同的委托类型。
例如:
delegate int A(int x);
delegate int B(int x);
A和B是两个不同的委托。
但是,两个结构一样的委托,它们的实例可以指向同一个方法。
3.委托的调用列表(多播委托)
委托实例所封装的方法集合称为调用列表。
当我们从某个方法创建一个委托实例的时候,该实例将封装此方法,该实例中的调用列表包含一个“入口点”。当我们组合多个非空的委托实例的时候,它们的调用列表将连接在一起形成一个新的调用列表,新的调用列表中包含了多个“入口点”。
委托的组合是使用二元运算符 + 和 += 来进行的,同样可以使用 - 和 -= 来进行组合的移除。
下面的示例演示多个委托的实例化及其相应的调用列表:
delegate void D(int x)
class
{
public static void M1(int i){...}
public static void M2(int i){...}
}
class Test
{
static void Main()
{
D cd1 = new D(c.M1); //M1
D cd2 = new D(c.M2); //M2
D cd3 = cd1 + cd2; //M1 + M2
D cd4 = cd3 + cd1; //M1 + M2 + M1
D cd5 = cd4 + cd3; //M1 + M2 + M1 + M2
}
}
实例化cd1和cd2的时候,它们分别封装一个方。实例化cd3的时候,它调用的列表有两个方法M1和M2,而且顺序与此相同。cd4的调用列表中依次包含M1、M2、M1。最后,cd5的调用列表中依次包含M2、M1、M1、M2。
4.委托的调用
当调用一个委托实例的时候,将按照调用列表的顺序依次调用列表中的各个方法,当在调用期间发生异常,调用列表中排在后面的任何方法将不会被调用。
using System;
delegate void D(int x);
class C
{
public static void M1(int i)
{
Console.WriteLine("C.M1:"+i);
} public static void M2(int i)
{
Console.WriteLine("C.M1:"+i);
} public void M3(int i)
{
Console.WriteLine("C.M2:"+i);
}
} class Test
{
static void Main()
{
D cd1 = new D(c.M1); //M1
cd1(-); //调用cd1 D cd2 = new D(c.M2); //M2
cd2(-); //调用M2 D cd3 = cd1 + cd2; //M1 + M2
cd3(); //依次调用M1、M2 cd3 += cd1;
cd3(); //依次调用M1、M2、M1 C c = new C();
D cd4 = new D(c.M3);
cd3 += cd4;
cd3(); //依次调用M1、M2、M1、M3 cd3 -= cd1 //移除最后一个M1
cd3(); //依次调用M1、M2、M3 cd3 -= cd4;
cd3(); //依次调用M1、M2 cd3 -= cd2
cd3(); //调用M1 cd3 -= cd2 //这是cd3的调用列表中没有cd2了,该移除不生效,不报错
cd3(); //调用M1 cd3 -= cd1
// cd3(70); //如果调用,将会报System.NullReferenceException异常
}
}
Lambda表达式
自从C#3.0开始,就可以使用一种新语法把实现代码赋予委托:Lambda表达式。只要有委托参数类型的地方,就可以使用Lambda表达式。使用匿名方法的地方可以使用Lambda表达式来代替,例如:
Func< string,string > = delagate(string para)
{
para += "Hello World!";
return param;
}
可以写成
Func< string,string > = para=>
{
para +="Hello World!";
return para;
}
Lambda表达式运算符”=>”的左边列出了需要的参数,右边定义了赋予Lambda变量的方法的代码实现。
我们注意到,无论何时,只要我们需要引入匿名方法,我们都需要在前面加上delegate关键字,而且参数列表都需要类型化。Lambda表达式提供了一种更为简洁和自然的语法,而且在C#更多高级的方面中都涉及广泛。简而言之,我们应该用Lambda表达式来替代匿名方法。
例如:
public class Person
{
string Name;
int Age;
} List<Person> personList = new List<Person>(); personList.Find(delegate(Person p){retrun p.Age==;});
//可以写成
personList.Find(p=>p.Age==);
转载 C#匿名函数 委托和Lambda表达式的更多相关文章
- 闭包(Closure)和匿名函数(Anonymous function)/lambda表达式的区别
闭包(Closure)和匿名函数(Anonymous function)/lambda表达式的区别 函数最常见的形式是具名函数(named function): function foo(){ con ...
- 委托学习过程及委托、Lambda表达式和匿名方法的关系总结及事件总结
第一章,当开始学习委托的时候,我们会问什么是委托?为什么要学习委托? 一,什么是委托? 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法, ...
- 匿名函数、委托和Lambda表达式
匿名函数 匿名函数(Anonymous Function)是表示“内联”方法定义的表达式.匿名函数本身及其内部没有值或者类型,但是可以转换为兼容的委托或者表达式树类型(了解详情).匿名函数转换的计算取 ...
- 深入学习C#匿名函数、委托、Lambda表达式、表达式树类型——Expression tree types
匿名函数 匿名函数(Anonymous Function)是表示“内联”方法定义的表达式.匿名函数本身及其内部没有值或者类型,但是可以转换为兼容的委托或者表达式树类型(了解详情).匿名函数转换的计算取 ...
- [深入学习C#] 匿名函数、委托和Lambda表达式
匿名函数 匿名函数(Anonymous Function)是表示“内联”方法定义的表达式.匿名函数本身及其内部没有值或者类型,但是可以转换为兼容的委托或者表达式树类型(了解详情).匿名函数转换的计算取 ...
- 十二、C# 委托与Lambda表达式(匿名方法的另一种写法)
委托与Lambda表达式 1.委托概述 2.匿名方法 3.语句Lambda 4.表达式Lambda 5.表达式树 一.委托概述 相当于C++当中的方法指针,在C#中使用delegate 委托来 ...
- C#函数式程序设计之函数、委托和Lambda表达式
C#函数式程序设计之函数.委托和Lambda表达式 C#函数式程序设计之函数.委托和Lambda表达式 相信很多人都听说过函数式编程,提到函数式程序设计,脑海里涌现出来更多的是Lisp.Haske ...
- 委托、匿名委托、Lambda 表达式、Expression表达式树之刨根问底
本篇不是对标题所述之概念的入门文章,重点在阐述它们的异同点和应用场景.各位看官,这里就不啰嗦了,直接上代码. 首先定义一个泛型委托类型,如下: public delegate T Function&l ...
- C# 委托 (一)—— 委托、 泛型委托与Lambda表达式
C# 委托 (一)—— 委托. 泛型委托与Lambda表达式 2018年08月19日 20:46:47 wnvalentin 阅读数 2992 版权声明:此文乃博主之原创.鄙人才疏,望大侠斧正.此 ...
随机推荐
- 我见过的 Objective-C, 讲的最通俗易懂的入门教程....
http://www.cnblogs.com/mjios/category/454764.html ---- 给力...
- Jdk5.0中出现的新特性
掌握jdk5.0中出现的新特性1.泛型(Generics)2.增强的"for"循环(Enhanced For loop)3.自动装箱/自动拆箱(Autoboxing/unboxin ...
- 绕过图片格式限制上传木马获取WebShell
思路: 图片上传功能中,前端页面上传的是.png格式的图片文件,但是抓包Request中修改图片后缀为.php 可以绕过对上传文件格式的限制,文件的上传路径可以在上传后的页面或查看上传成功后的resp ...
- org.apache.http.ProtocolException: Target host is not specified
对于httpClient4.3访问指定页面,可以从下面的demo抽取方法使用. 注意:对于URL必须使用 http://开始,否则会有如下报错信息: Caused by: org.apache.htt ...
- JDK个目录,以及与环境变量的关系
最近学习过程中老是看JDK里面的东西,可每次都翻书找,找了又忘.JDK,我们今天来个了断吧........ 一:bin: JDK中所包含的开发工具的可执行文件,PATH环境变量应该包含一个指向此目录的 ...
- Java基于Servlet过虑器
- NuGet相关的文章
NuGet学习笔记(1)——初识NuGet及快速安装使用http://www.cnblogs.com/zhwl/p/3377510.html NuGet学习笔记(2) 使用图形化界面打包自己的类库ht ...
- redolog 大小的实验
前言:近日因工作需要,测试postgresql和MySQL在oltp对比测试,因结果差异太多(MySQL测试结果比较差,相同环境),寻求大神帮助,有幸得叶大师和姜大师指点,指出my.cnf配置文件in ...
- JSP内置标签 JSP中JavaBean标签 JSP开发模式 EL和JSTL快速入门
2 JSP内置标签(美化+业务逻辑) 1)为了取代<%%>脚本形式,使用JSP标签/JSP动作,目的:与JSP页面的美化,即JSP面页都是由标签组成,不再有其它的内容 2)JSP内 ...
- poj3274
很不错的hash 优化有两个方面:1.根据题目换一个更优化的算法 2.在算法运行过程中优化 这题除了暴力好像没别的办法了吧? 但是暴力也是有策略的! 到第i只牛特征为j的总数为sum[i,j]; 找到 ...