匿名函数

  匿名函数(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表达式的更多相关文章

  1. 转载 C#匿名函数 委托和Lambda表达式

    转载原出处: http://blog.csdn.net/honantic/article/details/46331875 匿名函数 匿名函数(Anonymous Function)是表示“内联”方法 ...

  2. 闭包(Closure)和匿名函数(Anonymous function)/lambda表达式的区别

    闭包(Closure)和匿名函数(Anonymous function)/lambda表达式的区别 函数最常见的形式是具名函数(named function): function foo(){ con ...

  3. 委托学习过程及委托、Lambda表达式和匿名方法的关系总结及事件总结

    第一章,当开始学习委托的时候,我们会问什么是委托?为什么要学习委托? 一,什么是委托? 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法, ...

  4. 深入学习C#匿名函数、委托、Lambda表达式、表达式树类型——Expression tree types

    匿名函数 匿名函数(Anonymous Function)是表示“内联”方法定义的表达式.匿名函数本身及其内部没有值或者类型,但是可以转换为兼容的委托或者表达式树类型(了解详情).匿名函数转换的计算取 ...

  5. 匿名函数、委托和Lambda表达式

    匿名函数 匿名函数(Anonymous Function)是表示“内联”方法定义的表达式.匿名函数本身及其内部没有值或者类型,但是可以转换为兼容的委托或者表达式树类型(了解详情).匿名函数转换的计算取 ...

  6. python学习之---匿名函数,返回函数,偏函数

    1. 返回函数: 所谓的返回函数,指的是函数作为返回值.高阶函数除了可以接受函数作为参数外,同样可以接受函数作为结果返回.以下是一个可变参数的求和例子,一般求和函数是如此这般定义的: >> ...

  7. 十二、C# 委托与Lambda表达式(匿名方法的另一种写法)

    委托与Lambda表达式   1.委托概述 2.匿名方法 3.语句Lambda 4.表达式Lambda 5.表达式树   一.委托概述 相当于C++当中的方法指针,在C#中使用delegate 委托来 ...

  8. C#函数式程序设计之函数、委托和Lambda表达式

    C#函数式程序设计之函数.委托和Lambda表达式 C#函数式程序设计之函数.委托和Lambda表达式   相信很多人都听说过函数式编程,提到函数式程序设计,脑海里涌现出来更多的是Lisp.Haske ...

  9. 委托、匿名委托、Lambda 表达式、Expression表达式树之刨根问底

    本篇不是对标题所述之概念的入门文章,重点在阐述它们的异同点和应用场景.各位看官,这里就不啰嗦了,直接上代码. 首先定义一个泛型委托类型,如下: public delegate T Function&l ...

随机推荐

  1. List.remove()的使用注意

    不使用forEach的循环 使用forEach循环 参考 今天修改一个bug,需要取一个List和一个Set的交集,使用了双重循环.想着提高循环效率,每加入一个交集中的元素,就将List中的元素删除, ...

  2. HEXO+Git+Github+域名搭建个人博客

    搭建个人博客可以分为以下五个部分 一.搭建本地环境(个人为Win10) 1.安装Git,下载地址:点击 下载后,按提示进行安装即可,作用是:把本地的内容提交到github上去 注意:官网下载速度不是很 ...

  3. linux sort排序命令的高级用法

    在linux中,使用sort按行进行排序是很简单的.不过有时,生活总是爱抛给你一个一个的问题.如果使用sort按多个列值排列,同时使用tab作为分隔符,而且对于某些列需要进行逆序排列,这样sort命令 ...

  4. GDB调试系列之了解GDB

    想要熟练利用GDB进行程序调试,首先要了解什么是GDB. 1. 什么是GDB GDB (the GNU Project Debugger) 是一个可以运行在大多数常见的UNIX架构.Windows.M ...

  5. 初学Qt——程序打包(环境vs2012+qt5.1.0)

    说来可笑,网上那么多的教程,偏偏结尾的时候就没有一个能详细的讲下关于程序的发布.开发Qt是这样,刚开始做web也是这样,因为是自学的,所以都没人可以教下,结果到了项目完成的最后总是要花费成吨的时间去查 ...

  6. Context与ApplicationContext的区别

    ApplicationContext并没有这个类,其实更应该叫做:Activity与Application在作为Context时的区别.嗯,的确是这样的,大家在需要Context的时候,如果是在Act ...

  7. Implementing 5G NR Features in FPGA

    目录 论文来源 论文简介 基本原理 论文创新点 借鉴之处 论文来源 2018 European Conference on Networks and Communications (EuCNC),Ja ...

  8. web博客

    欢迎大家来戳一戳

  9. htm5新特性(转)

    转自:http://hyuhan.com/2017/07/06/... 今天来谈谈前端面试中基本上每次一面都会被问到的一个问题,那就是html5的新特性了.这个是学习前端必须掌握的基础知识. 新增的元 ...

  10. 课题:html5图像羽化(不规则区域羽化,feather,html5羽化)

    下午搜索了一堆相关文章,没有找到符合要求的. 对一张图片应用不规则区域的羽化,该怎么做呢? 首先去查了下 羽化的原理,然而没有什么用, 然后就开始从表现层去研究怎么模拟? idea 1: blur滤镜 ...