[深入学习C#]匿名函数、委托和Lambda表达式

转载自诗人江湖老,原文地址

  匿名函数(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);            //M1D cd2 = new D(c.M2);            //M2D cd3 = cd1 + cd2;              //M1 + M2D cd4 = cd3 + cd1;              //M1 + M2 + M1D 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);            //M1cd1(-1);                        //调用cd1D cd2 = new D(c.M2);            //M2cd2(-2);                        //调用M2D cd3 = cd1 + cd2;              //M1 + M2cd3(10);                        //依次调用M1、M2cd3 += cd1;cd3(20);                        //依次调用M1、M2、M1C c = new C();D cd4 = new D(c.M3);            cd3 += cd4;cd3(30);                        //依次调用M1、M2、M1、M3cd3 -= cd1                      //移除最后一个M1cd3(40);                        //依次调用M1、M2、M3cd3 -= cd4;                     cd3(50);                        //依次调用M1、M2cd3 -= cd2cd3(60);                        //调用M1cd3 -= cd2                      //这是cd3的调用列表中没有cd2了,该移除不生效,不报错cd3(70);                        //调用M1cd3 -= 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==12;});
//可以写成
personList.Find(p=>p.Age==12);

添加链接描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/548648.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HCIA第九节课作业

子网划分&#xff1a; 如何去合理的分配地址 总共需要多少个网段&#xff1f; 14个网段 环回接口8个6个 192.168.1.0/14 借4位 192.168.1.0/28 192.168.1.16/28 192.168.1.32/28 192.168.1.48/28 可用地址数量是多少?14个地址 子网划分第多少位的时候,只有两个可…

如何下载防盗链的歌曲?

初音&#xff0c;大家都很熟悉了。它是YAHAMA&#xff08;雅马哈&#xff0c;就是生产电子琴的那个公司&#xff09;推出的音乐编辑软件vocaloid的一款产品。 1月27号&#xff08;春节放假回来的前一天&#xff09;就要推出vocaloid 3啦&#xff01;&#xff01; 很喜欢IA的《鸟…

SQL Server大量数据秒级插入/新增/删除

转载自诗人江湖老,原文地址 /// <summary>/// 快速保存数据&#xff0c;自动识别insert和update/// </summary>/// <param name"_sourceTable">需要保存的源数据表</param>/// <param name"_sqlCon">数据库连接</param&g…

在当前主机添加两块网卡,将两块网卡绑定实现网卡冗余操作。

编辑虚拟网络接口配置文件,指定网卡IP 1. change the /etc/sysconfig/network-scripts/ifcfg-bond0 configuration. # cat ifcfg-bond0 DEVICEbond0 BOOTPROTOstatic IPADDR172.24.80.168 NETMASK255.255.255.0 BROADCAST172.24.80.250 ONBOOTyes TYPEEthernet # 不…

如何发布.Net MVC 网站项目(攻略集锦)

转载自诗人江湖老&#xff0c;原文地址 参考文献既然是攻略&#xff0c;就必然有参考文献&#xff0c;放在文章开头&#xff0c;以示敬意&#xff01; 1.MVC项目发布步骤 2.未能从程序集加载“System.ServiceModel.Activation.HttpModule” 3. Win7 IIS 另一个程序正在使用此…

ssh建立原理 及配置两台主机的远程连接实现免密登陆

一、SSH是什么&#xff1f;具体的实现有哪些&#xff1f; SSH是一种协议标准 SSH是用在安全远程登录以及其它安全网络服务 二、SSH原理&#xff1a; SSH为Secure Shell的缩写&#xff0c;默认端口22&#xff0c;由IETF的网络小组&#xff08;Network Working Group&…

ssh-scan处理手记

登陆一台Linux RedHat As4的服务器&#xff0c;发现有很多网络连接&#xff0c;为本机去连接其他服务器的22端口。再一看进程&#xff0c;好多ssh-scan的进程。估计是密码设得太简单&#xff0c;被人家黑了。处理思路&#xff1a;找到ssh-scan进程的相应程序文件&#xff0c;删…

常用 SQL Server 规范集锦

原文地址 常见的字段类型选择   &#xff11;.字符类型建议采用varchar/nvarchar数据类型   &#xff12;.金额货币建议采用money数据类型   &#xff13;.科学计数建议采用numeric数据类型   &#xff14;.自增长标识建议采用bigint数据类型 (数据量一大&#xff…

Linux服务器搭建----Web服务器(apache)

WWW的介绍 万维网&#xff08;亦作“Web”、“WWW”、“W3”&#xff0c;英文全称为“World Wide Web”&#xff09;&#xff0c;是一个由许多互相链接的超文本组成的系统&#xff0c;通过互联网访问。在这个系统中&#xff0c;每个有用的事物&#xff0c;称为一样“资源”&…

Pa interface issue——PA_EXCEED_ROUND_LIMIT

最近处理一个PA_TRANSACTION_INTERFACE_ALL的Error Error_code:PA_EXCEED_ROUND_LIMIT 原因是PA_EXCEED_ROUND_LIMIT is null or too small for cost*invoice_rate - cost*actual_rate. 就是说limit的value为空或者不满足金额*当前汇率与金额*录入时汇率的差额。 问题的难点在于…

C#实现 Linq 序列的Distinct—— IEnumerable.Distinct()——IEqualityComparer

转载自诗人江湖老&#xff0c;原文地址 在C#中使用List或者Collection的时候&#xff0c;我们经常需要使用到Distinct操作&#xff0c;但是微软默认提供的Distinct重载方法并不能满足我们的需求。这时候&#xff0c;我们就需要自己动手做一番工作了。 Distinct方法的重载 Linq…

F5 配置手册 -F5 BIG-IP 10.1-1-激活

F5 配置手册 F5 BIG-IP 10.1-1-激活 统一沟通(中国)有限公司 2012-01-29 前言&#xff1a; F5---太贵! 不过你如果有命运看到这个文章,F5也就不值钱了。 因为:F5提供测试版的虚拟机,我们买不起,总应该玩得起吧! 但愿F5提供更多的机会,给别人机会,也是给自己机会。 参照: 你也可…

[深入学习C#]利用反射给对象赋值

转载自诗人江湖老&#xff0c;原文地址  C#中利用反射能够获取对象的属性信息&#xff0c;也可以利用反射给对象赋值。 我们如果想利用凡是给一个对象属性赋值可以通过PropertyInfo.SetValue()方式进行赋值&#xff0c;但要注意值的类型要与属性保持一致。   假设我们有如下…

快速配置 Samba 将 Linux 目录映射为 Windows 驱动器

一、局域网内的 Linux 服务器上操作步骤&#xff1a;  1、安装samba&#xff08;CentOS Linux&#xff09;&#xff1a; yum install samba system-config-samba samba-client samba-common2、创建www账号 /usr/sbin/groupadd www/usr/sbin/useradd -g www wwwcat /etc/passw…

用委托来实现IEqualityComparer接口

转载自诗人江湖老&#xff0c;原文地址 class FuncEqualityComparer<T> : IEqualityComparer<T> {readonly Func<T, T, bool> _comparer;readonly Func<T, int> _hash;public FuncEqualityComparer( Func<T, T, bool> comparer ): this( compar…

Beginning iCloud in iOS 5 Tutorial Part 2(转载)

原文地址&#xff1a;http://www.raywenderlich.com/6031/beginning-icloud-in-ios-5-tutorial-part-2 Setting Up the User Interface The Xcode project template we chose already set up an empty view controller for us. We will extend it by adding the current docume…

JQuery Datatables 服务端分页简单应用学习

背景介绍 最近在一个简单小项目中碰到需要一个前端数据表格控件&#xff0c;在看了网上的资料后最终选择了JQuery Datatables。Datatables功能及其强大&#xff0c;基本满足我的所有需求&#xff0c;在加上其插件Editor具有inline模式&#xff0c;很多需要直接修改数据的功能不…

开源文化与开源社区

开源文化的形成  1998年2月8日&#xff0c;Bruce Perens发表的著名文章“TheOpen Source Definition”让当时众多的开源爱好者&#xff08;大多是***和程序员&#xff09;对开源理念有了一个清晰的认识。在那之后&#xff0c;更多的人开始关注开源所带来的实用意义和背后的文…

C#利用反射实现实体类ListT索引器

相关背景: 在项目开发中&#xff0c;我们经常会自定义一些实体类&#xff0c;在某些需要动态赋值的功能中&#xff0c;我们无法知道到下一个需要赋值的字段名称是什么&#xff0c;只知道会从其他返回需要赋值的字段名称和值&#xff0c;这时候就需要实现索引器了&#xff0c;就…

C#利用反射将Datatable转化为指定实体类ListT

背景介绍 在软件开发中肯定免不了和数据库打交道&#xff0c;我们对数据的增删改查最终会转化为SQL在数据库中执行。从SQLServer中查出数据一般有两种方式&#xff1a;一是ADO.NET直接写SQL语句从数据中查出数据&#xff0c;另一种是利用ORM框架得到数据。ADO.NET作为传统的数据…