委托到匿名方法到lambda表达式
2018-06-22 07:45:47来源:未知 阅读 ()
什么是委托
一个典型的例子,当一个方法的整体是相对固定不变的,而一小部份发生了变化,在没有委托这个东西有时候,我们通常的做法是:传一个变量到方法里,方法根据这个参数值来判断这些变化的部份的具体执行,说得很抽象,整个栗子:
using System; namespace DemoDelegate { class Program { static void Main(string[] args) { string input = Console.ReadLine(); string result = HandleString(input, "trim"); Console.WriteLine("没有委托时,我也能达到目的。result=" + result); } /// <summary> /// 将输入的内容前,追加上时间,再做相应的处理 /// </summary> /// <param name="ActoinType"></param> /// <returns></returns> private static string HandleString(string input, string ActoinType) { switch (ActoinType) { case "trim": input = input.Trim(); break; case "toLowerCase": input = input.ToLower(); break; case "toUpperCase": input = input.ToUpper(); break; default: break; } input = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffffff") + input;//这就是所说的固定不变的操作 return input; } } }
ps:以上代码中存在不足,看完或者会想:何不先将要处理的变化的那部分在main中进行处理,再调用。回答是:当方法HandleString足够复杂,上下文紧扣时,这个法想就要作罢了。
而按照面向对象封装的思想,这很明显是不符合扩展开放要求的。这时候自然就想,能不能将那变化的部份,以一个方法的形式传进去呢?灯灯灯灯!委托出现
想法:HandleString接收这个变化部份的方法叫什么类型呢?肯定不是将一个方法的调用写在参数里,因为这样就相当于将处理结果给了HandleString。它应该是一个新的数据类型:自己定义的一个类型。那么,先看个傻x问题:我们怎么定义一个类:
class CatInfo { public int ID { get; set; } public string Name { get; set; } }
class本身是一个关键字,那们我们就用delegate来做为定义一个方法类的类型
public delegate string WhatToDo(string input);
这时候,delete 就想当于class关键字,而这个类,不是平时定义的类那样,有属性,字段,方法。它只是定义了一类方法,如例子,这类方法是一定返回string,方法签名中是输入一个string。这种定义一类方法的方法,就叫委托了。
再看下傻x问题,我们怎么实例化一个类。
CatInfo info = new CatInfo();
同理地,我们这个实例化一个委托
public static string Method1(string input) { string result = "我就是一个普通的方法,返回string。输入参数也是一个string,我的输入值是:" + input; Console.WriteLine(result); return result; } WhatToDo instrnceOfWhatToDo = Method1;
是的,没有new关键字,类型 类型实例=具体值(即int a=1)就可以,仔细理解下,它无非就是一个方法类型(委托),为它赋值指向了某一个方法嘛。这时候,理解一个完整的栗子就不难了:
using System; namespace DemoDelegate { class Program { public delegate string WhatToDo(string input); static void Main(string[] args) { WhatToDo instrnceOfWhatToDo = DoTrim; string input = Console.ReadLine(); string result = HandleString(input,instrnceOfWhatToDo); Console.WriteLine("我会有相同的输出结果。result=" + result); } public static string DoTrim(string input) { string result = input.Trim();//脑补这里有很复杂的逻辑要处理 return result; } private static string HandleString(string input, WhatToDo TheInstanceOfWhatToDo) { input = TheInstanceOfWhatToDo(input); return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffffff") + input; } } }
总结下:委托,就是具有除方法名外的其它签名信息(输入参数个数和类型、返回参数类型)均相同的方法类型定义
有什么用
上面的栗子中,不易体现出委托的用途,但也不难体会出来一点眉目:它有对方法的颗粒数进行拆解的作用。至少像上面例子中,不再需根据ActoinType参数进行一堆判断,有更多变化时,不会违反开闭原则。根据定义好的WhatToDo,写个方法赋给这个委托的实例去调就便可。(当然这样每次扩展,都得定义一个方法的做法很麻烦,并且也没多少重用的可能性。不必担心,后面有简单写法,先挖个坑。
-----------------------------------------来个恶心的分隔线------------------------------------------------
什么是事件??后面再说明,再挖个坑,日后来填。
-----------------------------------------分隔线 again------------------------------------------------
委托变成匿名方法
基本功理解了,接下来便到了委托的具体玩法。填上前面埋的第一个坑。
要做一个委托,得声名一个一个委托类型,再有一个实例,再有这个实例指向的方法。引用papi酱的话“你说虐不虐?虐不虐?虐啊!”
至少,.net framework为我们做了一点点工作。因为方法的输入参数有限,那么.net framework可以帮我们定义好委托类型嘛!好好利用泛型便行。
它就是Func和Action,Func有返回值,Action 无返回值,看下定义:
Func<TResult>
Func<T, TResult>
Func<T1,T2, TResult>
Func<T1,T2,T3 TResult>
.....
Func就是定义好N个多重载的委托定义(N好大,反正使用也不可能一个方法个有那么多输入参数)。从没有输入参数,返回TResult,到有n个输入参数,返回TResult,都定义好的。
见栗子
static void Main(string[] args) { Func<string, DateTime, decimal, string> Method1 = MyMethod; Method1("张三", DateTime.Now, (decimal)18.00); } public static string MyMethod(string parms1, DateTime parms2, decimal parms3) { return "我是一个由string datetim decimal作为输入参数,返回string的方法"; }
跟委托最传统的写法没多少区别吧,只是少了定义一个委托类型。直接使用.net framework定义好的Func而已。
同理,Action也是定义好的委托,只不过没返回类型。
Action
Action<T1>
Action<T1,T2>
Action<T1,T2,T3>
还是得上栗子,即使太好理解了:
static void Main(string[] args) { Action<string, DateTime, decimal> Method1 = MyMethod; Method1("张三", DateTime.Now, (decimal)18.00); } public static void MyMethod(string parms1, DateTime parms2, decimal parms3) { Console.WriteLine("我是一个由string datetim decimal string作为输入参数,没有返回值的方法"); }
-----------------------------------------分隔线 again and again------------------------------------------------
委托的变化肯定不仅仅是.net framework帮我们定义好几个委托类型便完事。这时候,匿名方法出场。
我就不定义委托类型啦,用上面的Func,即学即用嘛。
using System; namespace Demo匿名方法 { class Program { static void Main(string[] args) { Func<int, int, int> myMethodPlus = delegate (int a, int b) { return a + b; }; Func<int, int, int> myMethodDivision = delegate (int a, int b) { if (b==0) { return 0; } return a / b; }; } } }
这样的写法就很优美了,不用单独定义一个个方法,直接可以将方法体写在委托实例等于号后面。因为这个方法的重用机会接近0。这个叫匿名方法的东西,因为它没有方法名,却有输入参数,返回值,则此得名。
PS.我真的很难记住它的语法,因为工作中少用。最常用的是什么?看下面:
匿名方法变成lambda表达式
别想着匿名方法就很优美,C#的语法糖so sweet。
我们有lambda表达式,这个lambda,就是高中数学接触的那个希腊符号λ。让委托写得更赏心悦目。
using System; namespace DemoLambda { class Program { static void Main(string[] args) { Func<int, int, int> myMethodPlus = (int a, int b) => { return a + b; }; Func<int, int, int> myMethodDivision = (int a, int b) => { if (b == 0) { return 0; } return a / b; }; int result1 = myMethodPlus(1, 1); int result2 = myMethodDivision(4, 2); } } }
没错。连那个一开始就要百度翻译的delegate关键字都不见了,用=>代替。语法就是(参数1,参数2,可以一个参数都没有就写个括号)=>{方法体};
到这里,看懂了实现GetEnumlator方法的那些Where(Func<T,bool>),OrderBy(Func(T,TKey)的原理了吧。
后记:
做了程序猿那么多年,一直从这里学习东西,却没有分享过。终于有空第一次写blog。错误之处,多谢提出更正。
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- ASP.NET使用Ajax返回Json对象的方法 2020-03-23
- SqlDataReader指定转换无效的解决方法 2020-03-23
- .net下log4net使用方法详解 2020-03-19
- asp.net定点执行任务的方法 2020-03-18
- .NET随机数函数的生成方法 2020-03-18
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash