Lambda表达式学习

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

 

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

 

或者是

 

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

 

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

 

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

 

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

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

 

///<summary>
///这是一个泛型类,类名后面接着一个尖括号里面的那个t,是我们自己定义的,如果你高兴,你可以定义w,y,z,WC都没有问题!
///这个T表示说我们在实例化类的时候,需要告诉类,我们是用哪一种类型来进行操作.
///</summary>
///<typeparamname="T"></typeparam>
public class MyList<T>
{
public List<T> _List{get;set;}
public MyList()
{
 this._List=new List<T>();
}
///<summary>
///用来连接所有元素用
///</summary>
///<returns>连接后的字符串</returns>
public string JoinOut()
{
 StringBuilder stbTemp=new StringBuilder();
 foreach(var item in_List)
 {
  stbTemp.Append(item);
  stbTemp.Append("<BR>");
 }
return stbTemp.ToString();
}
///<summary>
///所有元素的长度
///</summary>
///<returns>元素的整体长度</returns>
public int AllLen()
{
 StringBuilder stbTemp=new StringBuilder();
 foreach(varitem in _List)
  {
 stbTemp.Append(item);
 }
 return stbTemp.Length;
 }
 
 }

 

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

 

public int AllLen()
{
//StringBuilderstbTemp=newStringBuilder();
//foreach(varitemin_List)
//{
//stbTemp.Append(item);
//}
//returnstbTemp.Length;

 StringBuilder stbTemp=new StringBuilder();
 var type=typeof(T);
 if(type==typeof(string))
 {
 foreach(varitem in_List)
 {
 stbTemp.Append(item);
 stbTemp.Append("<BR>");
 }
 return stbTemp.Length;
 }
 if(type==typeof(int))
 {
 int intSum=0;
 foreach(varitem in_List)
 {
 intSum+=int.Parse(item.ToString());
 }
 return stbTemp.Length;
 }
 
/*这里可能还需要根据不同的类型进行不同的处理
*/

return 0;
}

 

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

 

 

//写一个委托,谁愿意做什么操作就自己写去,哥不管了!
public delegate int delegateAllLen<T>(List<T> list);
//写一个委托,谁愿意做什么操作就自己写去,哥不管了!
public delegateAllLen<T> FuncAllLen{get;set;}
public int AllLen()
{
if(FuncAllLen!=null)
{
return FuncAllLen(_List);
}
return 0;
}

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

 

 

///<summary>
///委托的实现
///</summary>
///<paramname="bln"></param>
///<returns></returns>
public int Temp(List<bool>bln)
{
int i=0;
foreach(varitem in bln)
{
  if(item) i++;
 }
  return i;
 }
 
 public void Main()
{
 var list = new MyList<bool>();
 
 list._List.Add(true);
 list._List.Add(false);
 list._List.Add(true);
///实现委托
 list.FuncAllLen+=Temp;
 MessageBox.Show(list.AllLen().ToString());
 }


现在我就轻松多了,可以去睡大觉了!所有的具体操作,前台编码人员自己去实现FuncAllLen这个委托去!我全部不管了!哈哈哈!
不过这样写可能还是有有点难以理解.一会定义一个

Delegate intdelegateAllLen<T>(List<T>list);一会又是

delegateAllLen<T> FuncAllLen{get;set;},都不知道那个是那个....
于是我采用C#3.5中委托的写法

 

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

public Func<List<T>,int>FuncAllLen{get;set;}

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

 

//我要使用最先进,最流行的拉姆达表达式!所以下面的这行委托我不需要了!哈哈哈哈
//publicFunc<List<T>,int>FuncAllLen{get;set;}

//
其实我把上面的委托定义放到函数里面当参数了....
public int AllLen(Func<List<T>,int>FuncAllLen)
{
if(FuncAllLen!=null)
{
return FuncAllLen(_List);
}
return0;
}

 

最后我们看看调用的方法

publicvoid Main()
{
var list=new MyList<bool>();

list._List.Add(true);
list._List.Add(false);
list._List.Add(true);
//传说中的拉姆达表达式出现了!!!!!!
int intRef=list.AllLen(
PList=>
{
inti=0;
foreach(var item in PList)
{
if(item)i++;
}
return i;
});
}

 

 

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

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

 

public void Main()
{
var intSumTemp=Sum((tempInt)=>{return tempInt+1;});
}

public int Sum(Func<int,int>func)
{
var int1=5;
int1+=5;
var intTemp=func(int1);
return intTemp*intTemp;
}

 

 

上面的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>(thisIEnumerable<TSource> source,Func<TSource,bool>predicate);
可写成vartemp=_List.Where(P=>{returntrue;});


public static int Sum<TSource>(thisIEnumerable<TSource> source,Func<TSource,int>selector);
可写成vartemp=_List.Sum(P=>P.count);

 

拉姆达表达式学习(2)

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

 

public class test
{
///<summary>
///定义一个委托
///</summary>
public Func<string> _GetName;
///<summary>
///一个普通的没有参数,有返回值的方法
///</summary>
///<returns></returns>
public string GetName()
{
return"张三";
}
public void Main()
{
//3.5以前的委托的实现,直接赋值
_GetName=GetName;

//拉姆达表达式的实现方法
_GetName=(
()//因为这个委托没参数,所以参数列表没有东西
=>//拉姆达表达式的符号
{//大括号的代码段表示具体的委托的实现
return "还是张三";
});
//拉姆达表达式的简写,如果委托的实现代码段中只有一句return则可以省略代码段最外面的大括号,return关键字
_GetName=()=>"总是张三";
//调用
string MyName=_GetName();
}
}

 

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

 

 

public class test
{
///<summary>
///定义一个委托,有一个参数和一个返回值
///</summary>
public Func<string,string> _GetName;
///<summary>
///有一个参数的方法
///</summary>
///<paramname="strName">这是一个参数!</param>
///<returns>这是一个返回值</returns>
public string GetName(stringstrName)
{
return strName;
}


public void Main()
{
//3.5以前的委托的实现,直接赋值
_GetName=GetName;

//拉姆达表达式的实现方法
_GetName=(
(S)//有一个参数!所以参数列表里面有一个东西,这个东西随大家高兴叫个阿猫阿狗都行!只要符合规范
=>//拉姆达表达式的符号
{//大括号的代码段表示具体的委托的实现
return "还是"+S;
});


//拉姆达表达式的简写,如果委托的实现代码段中只有一句return则可以省略代码段最外面的大括号,return关键字
_GetName=(abc)=>"总是"+abc;
//调用
string MyName=_GetName("张三");
}
}

 

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

 

public class test
{
///<summary>
///定义一个委托,有一个参数和一个返回值
///</summary>
public Func<string,int,string> _GetName;
///<summary>
///这是一个有两个参数的方法,方法的参数类型的顺序必须和委托的参数类型顺序一致
///</summary>
///<paramname="strName">第一个是字符类型</param>
///<paramname="intAGE">第二个是整形,请不要颠倒类型!</param>
///<returns>返回一个字符串,对应委托的最后一个参数</returns>
public string GetName(stringstrName,intintAGE)
{
return string.Format("{0}的年龄是{1}",strName,intAGE);
}
public void Main()
{
//3.5以前的委托的实现,直接赋值
_GetName=GetName;

//拉姆达表达式的实现方法
_GetName=(
(S,W)//有一个参数!所以参数列表里面有一个东西,这个东西随大家高兴叫个阿猫阿狗都行!只要符合规范
=>//拉姆达表达式的符号
{//大括号的代码段表示具体的委托的实现
return string.Format("{0}的年龄是{1}",S,W);
});
//拉姆达表达式的简写,如果委托的实现代码段中只有一句return则可以省略代码段最外面的大括号,return关键字
_GetName=(abc,efd)=>string.Format("{0}的年龄是{1}",abc,efd);
//调用
string MyName=_GetName("张三",33);
}
}

 

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

 

public class test
{
///<summary>
///定义一个委托,没有返回值也没有参数
///</summary>
public Action _GetName;

public void GetName()
{
System.Windows.Forms.MessageBox.Show("没有参数也没有返回值,我只要自己显示了!");
}
public void Main()
{
//3.5以前的委托的实现,直接赋值
_GetName=GetName;

//拉姆达表达式的实现方法
_GetName=(
()
=>//拉姆达表达式的符号
{//大括号的代码段表示具体的委托的实现
System.Windows.Forms.MessageBox.Show("没有参数也没有返回值,我只要自己显示了!");
});
//因为action没有返回值,所以下面的简写方式是错误的
//_GetName=()=>System.Windows.Forms.MessageBox.Show("
没有参数也没有返回值,我只要自己显示了!");
//
调用
_GetName();
}
}

 publicdelegate void Action<T>(Tobj);
有一个参数但没有返回值

 

 

public class test
{
///<summary>
///定义一个委托,没有返回值也没有参数
///</summary>
public Action<bool> _GetName;

public void GetName(boolblnShow)
{
if(blnShow)
{
System.Windows.Forms.MessageBox.Show("要我显示就显示,多没面子");
}
else
{
System.Windows.Forms.MessageBox.Show("不要我显示,我偏要显示");
}
}
public void Main()
{
//3.5以前的委托的实现,直接赋值
_GetName=GetName;

//拉姆达表达式的实现方法
_GetName=(
(b)
=>//拉姆达表达式的符号
{//大括号的代码段表示具体的委托的实现
if(b)
{
System.Windows.Forms.MessageBox.Show("要我显示就显示,多没面子");
}
else
{
System.Windows.Forms.MessageBox.Show("不要我显示,我偏要显示");
}
});

_GetName(true);
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值