`
v5browser
  • 浏览: 1136991 次
社区版块
存档分类
最新评论

拉姆达表达式学习(1)

 
阅读更多

转:http://www.cnblogs.com/shenfengok/archive/2011/10/10/2205363.html

我曾经遇到一个项目,项目里面需要经常对一系列的同类型集合进行操作,如对集合进行增加元素,删除集合的指定索引的元素等等.
  我们可以使用ArrayList来进行.

1ArrayListstringList=newArrayList();
2stringList.Add("大家好");
3stringList.Add("你们好");
4stringList.Add("同志们好");
5stringstr1=(string)stringList[0];//取出一个元素后,需要转换一次类型才可以

或者是

1ArrayListintList=newArrayList();
2intList.Add(6);
3intList.Add(8);
4intList.Add(66);
5intint1=(int)intList[0];//取出一个元素后,需要转换一次类型才可以

  但是ArrayList中的每个元素的类型都是Object(stringList[0]的类型是Object]),这意味着我们每一次的操作,其实都进行了隐式的类型转换,加入资料是把普通类型转换成Object类型,取出资料是把Object类型转换成普通类型.
  于是我在想象,如果有一种数组类型,在定义的时候,可以给出每个元素具体的类型,并且在赋值或者取值的时候,就是完全按照这个类型进行操作该多好.
  在.net2.0里面,我找到了List这个类型.List是一个泛型,我们看看List的使用

代码

1List<string>stringList=newList<string>();
2stringList.Add("大家好");
3stringstr1=stringList[0];//直接赋值成功!因为取出来的就是string对象
4//或者是
5List<int>intList=newList<int>();
6intList.Add(8);
7intint1=intList[0];//直接赋值成功!因为取出来的就是int对象

  大家可以看出,List在实例化的时候就需要定义一个类型,也就是尖括号中间的东西,在增加元素,或者获取元素的时候,操作的都是最开始定义的那种类型.List便是传说中的泛型类型.
  泛型可以用在方法上,也可以用在类上.如果看到某个方法或者类后面带有尖括号的,那么这个肯定就是泛型了.

  现在,我找到了能够有效的存储我要操作的集合的类型,那么我们要解决一些操作了.
  我需要对集合进行一个连接输出(把所有的元素连接在一起,每个元素之间使用<BR>来分割),还需要知道所有元素的总长度.显然,光一个List类型是解决不了问题的.于是我自己定义了一个自己的泛型类型

代码

1///<summary>
2///这是一个泛型类,类名后面接着一个尖括号里面的那个t,是我们自己定义的,如果你高兴,你可以定义w,y,z,WC都没有问题!
3///这个T表示说我们在实例化类的时候,需要告诉类,我们是用哪一种类型来进行操作.
4///</summary>
5///<typeparamname="T"></typeparam>
6publicclassMyList<T>
7{
8publicList<T>_List{get;set;}
9publicMyList()
10{
11this._List=newList<T>();
12}
13///<summary>
14///用来连接所有元素用
15///</summary>
16///<returns>连接后的字符串</returns>
17publicstringJoinOut()
18{
19StringBuilderstbTemp=newStringBuilder();
20foreach(varitemin_List)
21{
22stbTemp.Append(item);
23stbTemp.Append("<BR>");
24}
25returnstbTemp.ToString();
26}
27///<summary>
28///所有元素的长度
29///</summary>
30///<returns>元素的整体长度</returns>
31publicintAllLen()
32{
33StringBuilderstbTemp=newStringBuilder();
34foreach(varitemin_List)
35{
36stbTemp.Append(item);
37}
38returnstbTemp.Length;
39}
40
41}

但是如果我在求元素长度的时候,要求如果是stirng则返回所有元素的长度,而是int的时候,则返回所有元素的和.于是我重写了AllLen方法

代码

1publicintAllLen()
2{
3//StringBuilderstbTemp=newStringBuilder();
4//foreach(varitemin_List)
5//{
6//stbTemp.Append(item);
7//}
8//returnstbTemp.Length;
9
10StringBuilderstbTemp=newStringBuilder();
11vartype=typeof(T);
12if(type==typeof(string))
13{
14foreach(varitemin_List)
15{
16stbTemp.Append(item);
17stbTemp.Append("<BR>");
18}
19returnstbTemp.Length;
20}
21if(type==typeof(int))
22{
23intintSum=0;
24foreach(varitemin_List)
25{
26intSum+=int.Parse(item.ToString());
27}
28returnstbTemp.Length;
29}
30
31/*这里可能还需要根据不同的类型进行不同的处理
32*/
33return0;
34}

我在整个项目中,会负责编写公用类库.我不知道其他前台编码人员需要什么样子的操作.并且前台编码人员会各处一些稀奇古怪的需求我,要我实现,如他想接受一系列的bool类型,然后判断所有结果为True的数量,或者传入一系列的日期,判断所有星期一的日期有多少个...等等.我比较懒,并且我非常不愿意去修改我已经写好的类库.所以我又对Allen进行了一次修改.

代码

1//写一个委托,谁愿意做什么操作就自己写去,哥不管了!
2publicdelegateintdelegateAllLen<T>(List<T>list);
3//写一个委托,谁愿意做什么操作就自己写去,哥不管了!
4publicdelegateAllLen<T>FuncAllLen{get;set;}
5publicintAllLen()
6{
7if(FuncAllLen!=null)
8{
9returnFuncAllLen(_List);
10}
11return0;
12}

我告诉前台编码人员,你们想做什么就先去实现委托FuncAllLen.然后调用AllLen方法.

代码

1///<summary>
2///委托的实现
3///</summary>
4///<paramname="bln"></param>
5///<returns></returns>
6publicintTemp(List<bool>bln)
7{
8inti=0;
9foreach(variteminbln)
10{
11if(item)i++;
12}
13returni;
14}
15
16publicvoidMain()
17{
18varlist=newMyList<bool>();
19
20list._List.Add(true);
21list._List.Add(false);
22list._List.Add(true);
23///实现委托
24list.FuncAllLen+=Temp;
25MessageBox.Show(list.AllLen().ToString());
26}
27
28

现在我就轻松多了,可以去睡大觉了!所有的具体操作,前台编码人员自己去实现FuncAllLen 这个委托去!我全部不管了!哈哈哈!
不过这样写可能还是有有点难以理解.一会定义一个delegate int delegateAllLen<T>(List<T> list);一会又是delegateAllLen<T> FuncAllLen { get; set; },都不知道那个是那个....
于是我采用C#3.5中委托的写法

代码

1/*
2publicdelegateintdelegateAllLen<T>(List<T>list);
3publicdelegateAllLen<T>FuncAllLen{get;set;}
4以上这两句,可以简写成下面的一句!
5*/
6publicFunc<List<T>,int>FuncAllLen{get;set;}

调用的方法和以前一样,可是编码人员告诉我:这样你方便了,我们可就麻烦了,每次都要记得在使用AllLen方法的时候,都要先把委托实现了.特别是新来的人,总是记不住.
正好,最近我在学习Linq,c#3.5中推出了拉姆达表达式,可以让委托更简单的实现!于是我最后一次重写AllLen方法

代码

1//我要使用最先进,最流行的拉姆达表达式!所以下面的这行委托我不需要了!哈哈哈哈
2//publicFunc<List<T>,int>FuncAllLen{get;set;}
3
4//其实我把上面的委托定义放到函数里面当参数了....
5publicintAllLen(Func<List<T>,int>FuncAllLen)
6{
7if(FuncAllLen!=null)
8{
9returnFuncAllLen(_List);
10}
11return0;
12}

最后我们看看调用的方法

代码

1publicvoidMain()
2{
3varlist=newMyList<bool>();
4
5list._List.Add(true);
6list._List.Add(false);
7list._List.Add(true);
8//传说中的拉姆达表达式出现了!!!!!!
9intintRef=list.AllLen(
10PList=>
11{
12inti=0;
13foreach(variteminPList)
14{
15if(item)i++;
16}
17returni;
18});
19}

具体我们来看看拉姆达表达式的用法!
拉姆达表达式由三个部分组成,=>是拉姆达中固定的符号,必须出现!
=>
左边的表达式是一个参数列表,是一组没有类型的字符(字符怎么写随意!只要符合命名规范就好了),每个字符表示一个参数,每个参数之间使用逗号分割.
:
如果有三个参数,则表达式为(A,B,C),或者是(P1,P2,P3),
=>
右边的是具体要实现的代码段,代码段里面可以使用参数列表中的参数进行各种运算.
:
{return P1+P2+p3;}
合起来就是 (P1,P2,P3)=>{return P1+P2+P3;}
如果参数只有一个,那么省去小括号:P1=>{return P1+10;}
如果具体的实现代码只有一句返回语句,则可以简写成 P1=>P1+10;

一定要注意,拉姆达表达式只是一个委托的定义而已,当程序运行到拉姆达表达式的时候,拉姆达表达式里面的语句是不会被立刻执行的,很多人在初学拉姆达或者委托的时候都会犯这种错误.
:

代码

1publicvoidMain()
2{
3varintSumTemp=Sum((tempInt)=>{returntempInt+1;});
4}
5
6publicintSum(Func<int,int>func)
7{
8varint1=5;
9int1+=5;
10varintTemp=func(int1);
11returnintTemp*intTemp;
12}

上面的intSumTemp的结果是121.
运行的顺序是:首先调用Sum方法而不会去执行拉姆达表达式.
然后得到int1=10的结果(5+5),
接着需要运行func,并且知道func的参数值是int1,10.
那么func是通过拉姆达表达式定义的,所以这个时候,我们把10传入拉姆大表达式中,进行运算得到11(10+1)
方法最后是一个平方操作.结果为121(11*11)

知道拉姆达的写法,和使用的方法,那么我们在什么情况下可以使用拉姆达表达式能?
当我们在使用一个方法,方法的参数是Func,Action,那么就可以使用拉姆达表达式了!
我们拿linq里面的方法举例!
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
可写成 var temp=_List.Where(P=>{return true;});
public static int Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector);
可写成 var temp=_List.Sum(P=>P.count);

拉姆达表达式学习(2)

.net3.5里面,委托的定义和实现被大大的简化了!使用关键字FuncAction就可以定义一个委托,使用拉姆达表达式就可以实现一个具体的委托.
Func
关键字是用来定义一个有返回值的委托,它一共有五个重载,我们介绍其中的三个
1 public delegate TResult Func<TResult>();
这表示一个没有参数,只有一个返回值的委托,返回值的类型就是TResult(泛型)

代码

1publicclasstest
2{
3///<summary>
4///定义一个委托
5///</summary>
6publicFunc<string>_GetName;
7///<summary>
8///一个普通的没有参数,有返回值的方法
9///</summary>
10///<returns></returns>
11publicstringGetName()
12{
13return"张三";
14}
15publicvoidMain()
16{
17//3.5以前的委托的实现,直接赋值
18_GetName=GetName;
19
20//拉姆达表达式的实现方法
21_GetName=(
22()//因为这个委托没参数,所以参数列表没有东西
23=>//拉姆达表达式的符号
24{//大括号的代码段表示具体的委托的实现
25return"还是张三";
26});
27//拉姆达表达式的简写,如果委托的实现代码段中只有一句return则可以省略代码段最外面的大括号,return关键字
28_GetName=()=>"总是张三";
29//调用
30stringMyName=_GetName();
31}
32}

2 public delegate TResult Func<T, TResult>(T arg);
这表示有且仅有一个参数,并且有返回值的委托.

代码

1publicclasstest
2{
3///<summary>
4///定义一个委托,有一个参数和一个返回值
5///</summary>
6publicFunc<string,string>_GetName;
7///<summary>
8///有一个参数的方法
9///</summary>
10///<paramname="strName">这是一个参数!</param>
11///<returns>这是一个返回值</returns>
12publicstringGetName(stringstrName)
13{
14returnstrName;
15}
16publicvoidMain()
17{
18//3.5以前的委托的实现,直接赋值
19_GetName=GetName;
20
21//拉姆达表达式的实现方法
22_GetName=(
23(S)//有一个参数!所以参数列表里面有一个东西,这个东西随大家高兴叫个阿猫阿狗都行!只要符合规范
24=>//拉姆达表达式的符号
25{//大括号的代码段表示具体的委托的实现
26return"还是"+S;
27});
28//拉姆达表达式的简写,如果委托的实现代码段中只有一句return则可以省略代码段最外面的大括号,return关键字
29_GetName=(abc)=>"总是"+abc;
30//调用
31stringMyName=_GetName("张三");
32}
33}

3 public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
这表示有且仅有两个参数,并且有返回值的委托.

代码

1publicclasstest
2{
3///<summary>
4///定义一个委托,有一个参数和一个返回值
5///</summary>
6publicFunc<string,int,string>_GetName;
7///<summary>
8///这是一个有两个参数的方法,方法的参数类型的顺序必须和委托的参数类型顺序一致
9///</summary>
10///<paramname="strName">第一个是字符类型</param>
11///<paramname="intAGE">第二个是整形,请不要颠倒类型!</param>
12///<returns>返回一个字符串,对应委托的最后一个参数</returns>
13publicstringGetName(stringstrName,intintAGE)
14{
15returnstring.Format("{0}的年龄是{1}",strName,intAGE);
16}
17publicvoidMain()
18{
19//3.5以前的委托的实现,直接赋值
20_GetName=GetName;
21
22//拉姆达表达式的实现方法
23_GetName=(
24(S,W)//有一个参数!所以参数列表里面有一个东西,这个东西随大家高兴叫个阿猫阿狗都行!只要符合规范
25=>//拉姆达表达式的符号
26{//大括号的代码段表示具体的委托的实现
27returnstring.Format("{0}的年龄是{1}",S,W);
28});
29//拉姆达表达式的简写,如果委托的实现代码段中只有一句return则可以省略代码段最外面的大括号,return关键字
30_GetName=(abc,efd)=>string.Format("{0}的年龄是{1}",abc,efd);
31//调用
32stringMyName=_GetName("张三",33);
33}
34}

Action关键字用来定义一个没有返回值的方法,它有一个非泛型方法,和四个泛型方法,一共五种.Actionfunc的区别就在于一个没有返回值,一个有返回值!其他的都一样!就好像VBsubfunction一样!
1 public delegate void Action();
没有参数也没有返回值

代码

1publicclasstest
2{
3///<summary>
4///定义一个委托,没有返回值也没有参数
5///</summary>
6publicAction_GetName;
7
8publicvoidGetName()
9{
10System.Windows.Forms.MessageBox.Show("没有参数也没有返回值,我只要自己显示了!");
11}
12publicvoidMain()
13{
14//3.5以前的委托的实现,直接赋值
15_GetName=GetName;
16
17//拉姆达表达式的实现方法
18_GetName=(
19()
20=>//拉姆达表达式的符号
21{//大括号的代码段表示具体的委托的实现
22System.Windows.Forms.MessageBox.Show("没有参数也没有返回值,我只要自己显示了!");
23});
24//因为action没有返回值,所以下面的简写方式是错误的
25//_GetName=()=>System.Windows.Forms.MessageBox.Show("没有参数也没有返回值,我只要自己显示了!");
26//调用
27_GetName();
28}
29}

2 public delegate void Action<T>(T obj);
有一个参数但没有返回值

代码

1publicclasstest
2{
3///<summary>
4///定义一个委托,没有返回值也没有参数
5///</summary>
6publicAction<bool>_GetName;
7
8publicvoidGetName(boolblnShow)
9{
10if(blnShow)
11{
12System.Windows.Forms.MessageBox.Show("要我显示就显示,多没面子");
13}
14else
15{
16System.Windows.Forms.MessageBox.Show("不要我显示,我偏要显示");
17}
18}
19publicvoidMain()
20{
21//3.5以前的委托的实现,直接赋值
22_GetName=GetName;
23
24//拉姆达表达式的实现方法
25_GetName=(
26(b)
27=>//拉姆达表达式的符号
28{//大括号的代码段表示具体的委托的实现
29if(b)
30{
31System.Windows.Forms.MessageBox.Show("要我显示就显示,多没面子");
32}
33else
34{
35System.Windows.Forms.MessageBox.Show("不要我显示,我偏要显示");
36}
37});
38
39_GetName(true);
40}
41}


不过通常funcaction并不是单独定义,然后使用,而是当作某个方法的参数的类型

分享到:
评论

相关推荐

    拉姆达表达式C#的新特性

    我在网上看到的就下下来啦,给大家一个参考,是关于拉姆达表达式的一些资料

    委托、事件、Lambda表达式Demo

    博文《理解什么是委托、事件、Lambad表达式,从回调说起!》Demo

    浅谈C++11新引入的lambda表达式

    1.[capture list]捕获列表,捕获到函数体中,使得函数体可以访问 2.(parameter list)参数列表,用来表示lambda表达式的参数列表 3.-&gt;return type函数返回值 {function body}就是函数体 lambda表达式可以理解为一个...

    让JavaScript拥有类似Lambda表达式编程能力的方法

    在前几天的博文中我发布了一个可以自定义页码呈现方式的组件,有C#和JavaScript两个版本。

    Linq与Lambda分组语法取泛型数组某列的最小/大值

    使用Linq语法与Lambda表达式分组取泛型数组某列的最小值/最大值

    java8新特性

    主要是java8的新特性Stream的用法,里面用到了拉姆达表达式

    C#MVC开发模式资源视频

    C#MVC开发模式资源视频,包含linq查询,拉姆达表达式,EF实体数据模型等等等等

    DVD管理系统

    使用的编程工具是:visual studio 编写的内容是:DVD管理系统 用到的知识点是:泛型集合、拉姆达表达式

    Android仿豆瓣app,优秀毕业设计源代码,功能丰富!

    * 首页分为三大模块,包括:电影、看书、音乐。...* 项目整体采用mvp+rxjava+retrofit 框架,用butterknif注解,使用glide进行图片展示,另外使用了java8的拉姆达表达式,安卓原生并不支持,需要导插件。

    UDPtest.zip

    使用QT写的UDP通信,一端是用UI然后给对应的空间添加槽函数,另外一端是直接程序基于Wigets编写界面,是ui编写和程序编写的对比,也是槽函数与拉姆达表达式的对比,可供新手对比学习。运行后,两个程序可以相互发送...

    拉姆达

    拉姆达

    利用Lambda表达式创建新线程案例

    主要介绍了利用Lambda表达式创建新线程案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

    Linq to Entities

    Linq to entities的一个小例子,利用它可以很方便地完成数据库访问

    java8源码-RxJavaRetrofit:RxJava改造

    这个项目使用到了拉姆达表达式: 在安卓中使用Java 8 lambda表达式,很遗憾安卓原生不支持,需要用插件。 在工程中build.GRADLE导入: dependencies { classpath 'com.android.tools.build:gradle:2.1.0' classpath ...

    Cpp11ThreadPool:线程池,使用了很多C++ 11的新特性, 流程和传统的差不多,但是代码简洁了很多

    线程池,可以提交变参函数或拉姆达表达式的匿名函数执行,可以获取执行返回值代码不多,上百行代码就完成了 线程池, 并且, 看看 commit, 哈, 不是固定参数的, 无参数数量限制! 这得益于可变参数模板.*为了避嫌,先进行...

    JavaDataStructures:java中常见数据结构的实现

    Java 数据结构Java SE 8 拉姆达表达式功能接口方法参考流数据结构: 列表堆哈希表霍夫曼密码函数式编程ListModule 动态规划斐波那契濒海战斗舰2014/02/16 - 2014/03/16

    lambda-zone:Lambda 表达式战区

    拉姆达区 一个用于国际象棋策略功能的 Clojure 网站 转到此,其中解释了此应用程序的概念。 是一个类似于 TryClojure 和 4Clojure 网站的网站,它为开发人员提供了一个平台来提交自己的代码,在这种情况下是用 ...

    高斯拉姆达

    elmo式学习のlambdaは0で教师の胜败结果のみから学习し(Q-learning),1で浅い探索の评価値を胜率変换したものから教师の深い探索の评価値を胜率変换したものを引いたものだけを学习します。(Rootstrap) 诘み寸...

Global site tag (gtag.js) - Google Analytics