拉姆达表达式学习(1)
我曾經(jīng)遇到一個項目,項目里面需要經(jīng)常對一系列的同類型集合進行操作,如對集合進行增加元素,刪除集合的指定索引的元素等等.
我們可以使用ArrayList來進行.如
1ArrayListstringList=newArrayList();
2stringList.Add("大家好");
3stringList.Add("你們好");
4stringList.Add("同志們好");
5stringstr1=(string)stringList[0];//取出一個元素后,需要轉(zhuǎn)換一次類型才可以
或者是
1ArrayListintList=newArrayList();
2intList.Add(6);
3intList.Add(8);
4intList.Add(66);
5intint1=(int)intList[0];//取出一個元素后,需要轉(zhuǎn)換一次類型才可以
但是ArrayList中的每個元素的類型都是Object(stringList[0]的類型是Object]),這意味著我們每一次的操作,其實都進行了隱式的類型轉(zhuǎn)換,加入資料是把普通類型轉(zhuǎn)換成Object類型,取出資料是把Object類型轉(zhuǎn)換成普通類型.
于是我在想象,如果有一種數(shù)組類型,在定義的時候,可以給出每個元素具體的類型,并且在賦值或者取值的時候,就是完全按照這個類型進行操作該多好.
在.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便是傳說中的泛型類型.
泛型可以用在方法上,也可以用在類上.如果看到某個方法或者類后面帶有尖括號的,那么這個肯定就是泛型了.
現(xiàn)在,我找到了能夠有效的存儲我要操作的集合的類型,那么我們要解決一些操作了.
我需要對集合進行一個連接輸出(把所有的元素連接在一起,每個元素之間使用<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/*這里可能還需要根據(jù)不同的類型進行不同的處理
32*/
33return0;
34}
我在整個項目中,會負(fù)責(zé)編寫公用類庫.我不知道其他前臺編碼人員需要什么樣子的操作.并且前臺編碼人員會各處一些稀奇古怪的需求我,要我實現(xiàn),如他想接受一系列的bool類型,然后判斷所有結(jié)果為True的數(shù)量,或者傳入一系列的日期,判斷所有星期一的日期有多少個...等等.我比較懶,并且我非常不愿意去修改我已經(jīng)寫好的類庫.所以我又對Allen進行了一次修改.
代碼
1//寫一個委托,誰愿意做什么操作就自己寫去,哥不管了!
2publicdelegateintdelegateAllLen<T>(List<T>list);
3//寫一個委托,誰愿意做什么操作就自己寫去,哥不管了!
4publicdelegateAllLen<T>FuncAllLen{get;set;}
5publicintAllLen()
6{
7if(FuncAllLen!=null)
8{
9returnFuncAllLen(_List);
10}
11return0;
12}
我告訴前臺編碼人員,你們想做什么就先去實現(xiàn)委托FuncAllLen.然后調(diào)用AllLen方法.
代碼
1///<summary>
2///委托的實現(xiàn)
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///實現(xiàn)委托
24list.FuncAllLen+=Temp;
25MessageBox.Show(list.AllLen().ToString());
26}
27
28
現(xiàn)在我就輕松多了,可以去睡大覺了!所有的具體操作,前臺編碼人員自己去實現(xiàn)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;}
調(diào)用的方法和以前一樣,可是編碼人員告訴我:這樣你方便了,我們可就麻煩了,每次都要記得在使用AllLen方法的時候,都要先把委托實現(xiàn)了.特別是新來的人,總是記不住.
正好,最近我在學(xué)習(xí)Linq,c#3.5中推出了拉姆達表達式,可以讓委托更簡單的實現(xiàn)!于是我最后一次重寫AllLen方法
代碼
1//我要使用最先進,最流行的拉姆達表達式!所以下面的這行委托我不需要了!哈哈哈哈
2//publicFunc<List<T>,int>FuncAllLen{get;set;}
3
4//其實我把上面的委托定義放到函數(shù)里面當(dāng)參數(shù)了....
5publicintAllLen(Func<List<T>,int>FuncAllLen)
6{
7if(FuncAllLen!=null)
8{
9returnFuncAllLen(_List);
10}
11return0;
12}
最后我們看看調(diào)用的方法
代碼
1publicvoidMain()
2{
3varlist=newMyList<bool>();
4
5list._List.Add(true);
6list._List.Add(false);
7list._List.Add(true);
8//傳說中的拉姆達表達式出現(xiàn)了!!!!!!
9intintRef=list.AllLen(
10PList=>
11{
12inti=0;
13foreach(variteminPList)
14{
15if(item)i++;
16}
17returni;
18});
19}
具體我們來看看拉姆達表達式的用法!
拉姆達表達式由三個部分組成,=>是拉姆達中固定的符號,必須出現(xiàn)!
=>左邊的表達式是一個參數(shù)列表,是一組沒有類型的字符(字符怎么寫隨意!只要符合命名規(guī)范就好了),每個字符表示一個參數(shù),每個參數(shù)之間使用逗號分割.
如:
如果有三個參數(shù),則表達式為(A,B,C),或者是(P1,P2,P3),
=>右邊的是具體要實現(xiàn)的代碼段,代碼段里面可以使用參數(shù)列表中的參數(shù)進行各種運算.
如:
{return P1+P2+p3;}
合起來就是 (P1,P2,P3)=>{return P1+P2+P3;}
如果參數(shù)只有一個,那么省去小括號:P1=>{return P1+10;}
如果具體的實現(xiàn)代碼只有一句返回語句,則可以簡寫成 P1=>P1+10;
一定要注意,拉姆達表達式只是一個委托的定義而已,當(dāng)程序運行到拉姆達表達式的時候,拉姆達表達式里面的語句是不會被立刻執(zhí)行的,很多人在初學(xué)拉姆達或者委托的時候都會犯這種錯誤.
如:
代碼
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的結(jié)果是121.
運行的順序是:首先調(diào)用Sum方法而不會去執(zhí)行拉姆達表達式.
然后得到int1=10的結(jié)果(5+5),
接著需要運行func了,并且知道func的參數(shù)值是int1,即10.
那么func是通過拉姆達表達式定義的,所以這個時候,我們把10傳入拉姆大表達式中,進行運算得到11(10+1)
方法最后是一個平方操作.結(jié)果為121(11*11)
知道拉姆達的寫法,和使用的方法,那么我們在什么情況下可以使用拉姆達表達式能?
當(dāng)我們在使用一個方法,方法的參數(shù)是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);
本段作為講解拉姆達表達式的一個引文!下一章會給大家介紹一下Func和Action
總結(jié)
以上是生活随笔為你收集整理的拉姆达表达式学习(1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深信服EDR命令执行&任意用户登
- 下一篇: PG数据库恢复简单记录