Lambda表达式学习(1)

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

ArrayList stringArrayList = new ArrayList();
stringArrayList. Add("大家好");
stringArrayList. Add("你们好");
stringArrayList. Add("同志们好");
string str1 = (string)stringArrayList[0];//取出一个元素后 , 需要转换一次类型才可以

或者是

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

但是ArrayList中每个元素的类型都是Object(stringArrayList[0]的类型是Object) , 这意味着我们每一次的操作 , 其实都进行了隐式的类型转换 , 加入资料是把普通类型转换成Object类型 , 取出资料是把Object类型转换成普通类型.

  于是我在想象 , 如果有一种数组类型 , 在定义的时候 , 可以给出每个元素具体的类型 , 并且在赋值或者取值的时候 , 就是完全按照这个类型进行操作该多好.

  在. net2. 0里面 , 我找到了List这个类型. List是一个泛型 , 我们看看List的使用

代码
1 List<string> stringArrayList  =  new List<string>();
2 stringArrayList. Add("大家好");
3 string str1  =  stringArrayList[0];//直接赋值成功!因为取出来的就是string
4 //或者
5 List<int> intArrayList  =  new List<int>();
6 intArrayList. Add(8);
7 int int1 = intArrayList[0];//直接赋值成功!因为取出来的就是int

大家可以看出 , List在实例化的时候就需要定义一个类型 , 也就是尖括号中间的东西 , 在增加元素 , 或者获取元素的时候 , 操作的都是最开始定义的那种类型. List便是传说中的泛型类型.

  泛型可以用在方法上 , 也可以用在类上. 如果看到某个方法或者类后面带有尖括号的 , 那么这个肯定就是泛型了.

  现在 , 我找到了能够有效存储我要操作的集合类型 , 那么我们要解决一些操作了.

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

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

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

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

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

代码
 1     //写一个委托 , 谁愿意做什么操作就自己写去 , 哥不管了!
 2     public delegate int delegateAllLen<T>(List<T> list);
 3         //写一个委托 , 谁愿意做什么操作就自己写去 , 哥不管了!
 4         public delegateAllLen<T> FuncAllLen { get; set; }
 5         public int AllLen()
 6         {
 7             if (FuncAllLen ! =  null)
 8             {
 9                 return FuncAllLen(_List);
10             }
11             return 0;
12         }

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

代码
 1     /// <summary>
 2         /// 委托的实现
 3         /// </summary>
 4         /// <param name = "bln"></param>
 5         /// <returns></returns>
 6         public int Temp(List<bool> bln)
 7         {
 8             int i  =  0;
 9             foreach (var item in bln)
10             {
11                 if (item) i++;
12             }
13             return i;
14         }
15
16         public void Main()
17         {
18             var list  =  new MyList<bool>();
19
20             list. _List. Add(true);
21             list. _List. Add(false);
22             list. _List. Add(true);
23             ///实现委托
24             list. FuncAllLen + =  Temp;
25             MessageBox. Show(list. AllLen(). ToString());
26         }

现在我就轻松多了 , 可以去睡大觉了!所有的具体操作 , 前台编码人员自己去实现FuncAllLen 这个委托去!我全部不管了!哈哈哈!

不过这样写可能还是有有点难以理解. 一会定义一个delegate int delegateAllLen<T>(List<T> list);一会又是delegateAllLen<T> FuncAllLen { get; set; } , 都不知道那个是那个. . . .

于是我采用C#3. 5中委托的写法

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

调用的方法和以前一样 , 可是编码人员告诉我:这样你方便了 , 我们可就麻烦了 , 每次都要记得在使用AllLen方法的时候 , 都要先把委托实现了. 特别是新来的人 , 总是记不住.

正好 , 最近我在学习Linq , c#3. 5中推出了拉姆达表达式 , 可以让委托更简单的实现!于是我最后一次重写AllLen方法

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

最后我们看看调用的方法

代码
 1 public void Main()
 2         {
 3             var list  =  new MyList<bool>();
 4
 5             list. _List. Add(true);
 6             list. _List. Add(false);
 7             list. _List. Add(true);
 8         //传说中的拉姆达表达式出现了!!!!!!
 9             int intRef  =  list. AllLen(
10                 PList  = >
11                 {
12                     int i  =  0;
13                     foreach (var item in PList)
14                     {
15                         if (item) i++;
16                     }
17                     return i;
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;

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

代码
 1      public void Main()
 2         {
 3              var intSumTemp  =  Sum((tempInt)  = > { return tempInt + 1; });
 4         }
 5
 6         public int Sum(Func<int ,  int> func)
 7         {
 8         var int1 = 5;
 9         int1+ = 5;
10             var intTemp  =  func(int1);
11             return intTemp * 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);
时间: 2024-10-24 16:52:17

Lambda表达式学习(1)的相关文章

java lambda表达式学习笔记

lambda是函数式编程(FP,functional program),在java8中引入,而C#很早之前就有了.在java中lambda表达式是'->',在C#中是‘=>’. 杜甫说:射人先射马,擒贼先擒王.学习一个库要学习它的入口类.lambda的入口类是Stream,一看Stream中的函数就会发现Function,Predicate等lambda元素. 一.几个概念     函数式接口 Functional Interface,除了static和default类型的方法外,只有一个函数

java 8 中lambda表达式学习

转自 http://blog.csdn.net/renfufei/article/details/24600507 http://www.jdon.com/idea/java/10-example-of-lambda-expressions-in-java8.html Lambda表达式的语法基本语法:(parameters) -> expression或(parameters) ->{ statements; } 下面是Java lambda表达式的简单例子: // 1. 不需要参数,返回值

WPF-MVVM模式学习笔记4——Lambda表达式学习

在学习MVVM的过程中,其中自定义了一个超类NotificationObject,如下 public abstract class NotificationObject : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void RaisePropertyChanged(string propertyName) { PropertyChang

lambda表达式学习笔记(1) -- 作为委托的lambda表达式

C#中的Lambda表达式就是C# 2中匿名方法的演变,因此从一个匿名函数开始一步步简化写法. 例子是获取一个string参数,然后返回一个int. 首先匿名方法的写法如下: Func<string, int> returnLength; returnLength = delegate (string text) { return text.Length; }; Console.Write(returnLength("Hello")); lambda表达式最冗长的形式是:

C#Lambda表达式学习日记

Lambda表达式只是用更简单的方式来写匿名方法,彻底简化了对.NET委托类型的使用. 现在,如果我们要使用泛型 List<> 的 FindAll() 方法,当你从一个集合去提取子集时,可以使用该方法. // 该方法唯一的参数是一个System.Predicate<T>类型的泛型委托 public List<T> FindAll(Predicate<T> match); // 该委托指向任意以类型参数作为唯一输入参数并返回bool的方法 public del

C++11 lambda表达式学习

lambda表达式是函数式编程的基础.咱对于函数式编程也没有足够的理解,因此这里不敢胡言乱语,有兴趣的可以自己查找相关资料看下.这里只是介绍C++11中的lambda表达式自己的认识.这里有参考文档http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2927.pdf 给出两个例子,可以看出lambda表达式的写法 [](int x, int y) { return x + y; } [](int x, int y) -> int {

lambda表达式学习笔记

lambda表达式用于简化某些匿名内部类的写法: 1.无参函数的简写 new Thread(new Runnale(){ @overrie public void run(){ } }).start();\\ new Thread( () -> { .. ... }.start(); 2.带参数的简写 Collections.sort(list, new Comparator<String>(){// 接口名 @Override public int compare(String s1,

Lambda表达式学习篇二(流-上)

一.从外部迭代到内部迭代 使用for循环计算伦敦的艺术家人数: int count=0; for(Artist artist:allArtists){ if(artist.isFrom("London")){ count++; } } 每次迭代集合类时,都需要写较多样本代码. 调用iterator,产生一个新的Iterator对象,进而控制整个迭代过程,这就是外部迭代. int count=0; Iterator<Artist> iterator=allArtists.it

#Python中lambda表达式学习

#出处:http://mp.weixin.qq.com/s?__biz=MjM5NzU0MzU0Nw==&mid=202117122&idx=1&sn=1cf1f3f8abce89850da0da685ba4e771#rd#lambda的主体是一个表达式,而不是一个代码块.仅仅能在lambda表达式中封装有限的逻辑进去.#lambda表达式是起到一个函数速写的作用.允许在代码内嵌入一个函数的定义.#例如:f=lambda x,y,z:x+y+zprint f(1,2,3)#用lam

python第l六天,lambda表达式学习,涉及filter及Map。

在python中lambda表达式可以作为匿名函数来使用,举一个简单的栗子: 以前我们写两个数相加的函数需要 #以前我们写两个数相加的函数,需要这样写 >>> def sum(x,y): return x+y >>> sum(1,2) 3 >>> #而学了lambda之后我们再写这个函数可以这么写 >>> x=lambda x,y:x+y >>> x(1,2) 3 >>> python对我们以后的编