臺技術(shù)設(shè)計(jì)與應(yīng)用NET第二章V.ppt
《臺技術(shù)設(shè)計(jì)與應(yīng)用NET第二章V.ppt》由會員分享,可在線閱讀,更多相關(guān)《臺技術(shù)設(shè)計(jì)與應(yīng)用NET第二章V.ppt(99頁珍藏版)》請?jiān)谘b配圖網(wǎng)上搜索。
1,電子政務(wù)平臺技術(shù)設(shè)計(jì)與應(yīng)用,南大濱海學(xué)院法政學(xué)系張一鳴,電子政務(wù)平臺技術(shù)設(shè)計(jì)與應(yīng)用——ASP.NET高級應(yīng)用Version2,南大濱海學(xué)院法政學(xué)系張一鳴2016年2月10日,2,ASP.NET高級應(yīng)用第2章C#語言相關(guān)特性,南大濱海學(xué)院法政學(xué)系張一鳴2016年2月10日,電子政務(wù)平臺技術(shù)設(shè)計(jì)與應(yīng)用,3,本章主要內(nèi)容,本章主要是回顧和深入介紹在ASP.NET中涉及的C#中高級知識,包括泛型、匿名、lambda表達(dá)式、yield關(guān)鍵字、IEnumerable接口等。,,,,,,委托,,,對象初始化表達(dá)式,匿名與匿名方法,Lambda表達(dá)式,,,,,泛型,擴(kuò)展方法,,,枚舉量和Yield,,,查詢表達(dá)式,4,C#的新特征,對于使用ASP.NET的復(fù)雜功能來說,它完全依賴與C#中新增的一些概念和特征,因此可以說,泛型等概念和特征是這些應(yīng)用的基礎(chǔ)。本章將系統(tǒng)的介紹這些內(nèi)容,包括泛型、lambda表達(dá)式、匿名、yield關(guān)鍵字、IEnumerable接口等,為學(xué)生完全掌握LINQ技術(shù)打好基礎(chǔ)。,5,2.1代理(委托),C#調(diào)用方法時,可以向方法傳遞參數(shù)。這些參數(shù)分為按值、按引用或按輸出等類型。其中引用實(shí)際上就是原來變量即實(shí)參的別名,指向?qū)崊⒃趦?nèi)存中的位置,所以在方法中對引用類型參數(shù)的修改會導(dǎo)致對實(shí)參本身的改變。類似地,如果把方法也看成數(shù)據(jù),通過代理機(jī)制把方法賦值給一個變量,也就是把這個方法在內(nèi)存中的位置賦給變量,則通過這個變量就可以把這個方法傳遞給其他的方法調(diào)用。這種類型的變量就是代理類型的變量。,6,代理(委托)的實(shí)質(zhì),代理本身是一個類,它封裝了一個或多個方法。在內(nèi)部,一個代理保存方法指針(地址)的對照表,即這個代理類里面的每個方法名和它對應(yīng)的地址的列表。每個方法指針可以與一個引用實(shí)例配對,而該實(shí)例是包含實(shí)例方法的類實(shí)例。聲明代理類型時在方法頭前面放上關(guān)鍵字delegate,例如:publicdelegatevoidPrintCallback(intno);,7,例子2.1代理的應(yīng)用實(shí)例分析,本例是文書自動回信的局部功能演示。根據(jù)輸入的來信人姓名和性別,確定增加“先生”或“女士”的稱呼;根據(jù)處理來信時間,確定增加“你好”、“上午好”或“下午好”的問候語。這需要編制添加稱呼詞的兩個方法和添加時間問候詞的三個方法。為了在主程序中使代碼簡潔清晰,不用if語句分情況調(diào)用不同稱呼詞和問候語的辦法,而是采用兩個代理分別表示添加的內(nèi)容,問候語的區(qū)別通過代理的參數(shù)來解決。,8,例子2.1代理類型的應(yīng)用,usingSystem;NamespaceDemoDelegate1{delegatevoidmyDelegate(strings);//無返回類型//的代理,添加問候詞delegatestringmyDelegateStr(strings,boolman);//有返回類型的代理,添加稱呼詞classProgram{staticvoidshow1(strings){Console.WriteLine(“你好,{0}!”,s);}staticvoidshow2(strings){Console.WriteLine(“上午好,{0}!”,s);},9,例子2.1代理類型的應(yīng)用(續(xù)1),staticvoidshow3(strings){Console.WriteLine(“下午好,{0}!”,s);}staticstringAddTitle(strings,boolman){if(man)returnstring.Format(“你好,{0}先生!”,s);elsereturnstring.Format(“你好,{0}女士!”,s);},10,例子2.1(續(xù)2),staticvoidMain(string[]args){stringname=“林晚榮”;stringname2=“徐芷晴”;myDelegatedel1=newmyDelegate(show1);Console.WriteLine(“.NET代理調(diào)用”);del1(name);//代理調(diào)用,del1指向方法show1Console.WriteLine(“*******************************”);Console.WriteLine(“多路代理綁定調(diào)用”);del1+=show2;//代理del1在已綁定show1基礎(chǔ)上又添加//指向show2del1+=show3;//代理del1在原基礎(chǔ)上又添加指向show3,11,例子2.1(續(xù)3),del1(name);//代理調(diào)用,del1指向方法show1、//show2、show3Console.WriteLine(“\n合并掉show1代理調(diào)用”);del1-=show1;//代理del1現(xiàn)在僅指向show2、show3del1(name);//代理調(diào)用,del1僅指向方法show2和//show3Console.WriteLine(“*******************************”);myDelegatedel2=AddTitle;Console.WriteLine(“返回帶類型的綁定調(diào)用”);Console.WriteLine(del2(name,true));Console.WriteLine(del2(name2,false));}}},12,例子2.1代理的應(yīng)用實(shí)例運(yùn)行結(jié)果,,.NET代理調(diào)用你好,林晚榮!**************************************多路代理綁定調(diào)用你好,林晚榮!上午好,林晚榮!下午好,林晚榮!**************************************合并掉show1代理調(diào)用上午好,林晚榮!下午好,林晚榮!**************************************返回類型的代理調(diào)用你好,林晚榮先生!你好,徐芷晴女士!,13,例子2.2代理的應(yīng)用實(shí)例分析,本例是對一個有10個元素的整形數(shù)組,分別調(diào)用三個不同的方法過濾選出其偶數(shù)、奇數(shù)和大于5的數(shù)的子集并顯示。為了實(shí)現(xiàn)這個目的,一般是分別編寫篩選偶數(shù)的方法IsEven、篩選奇數(shù)的方法IsOdd和篩選大于5的數(shù)的方法IsOver5,然后在程序里分別調(diào)用它們來實(shí)現(xiàn)要求。更簡潔的辦法是采用代理技術(shù),設(shè)計(jì)一個代理類型NumPredicate和它的實(shí)例對象變量even-Predicate。在主程序每次執(zhí)行不同的任務(wù)時,都是調(diào)用同一個代理變量,只是分別給這個代理型變量賦值引用不同的方法。,14,例子2.2代理的應(yīng)用實(shí)例分析(續(xù)),IsEven、IsOdd和IsOver5這三個方法都接收一個整型參數(shù)int并判斷是否滿足條件,然后返回一個布爾型邏輯值。為了解決對數(shù)組全部元素過濾挑選的任務(wù),又設(shè)計(jì)了一個方法FilterArray,它接受待過濾的數(shù)組和代理類型NumPredicate的引用變量作為參數(shù),并按照每次引用變量所指向的方法對數(shù)組進(jìn)行具體的過濾操作。對每次選中的結(jié)果調(diào)用方法DisplayList全部顯示出來。本例中采用了列表結(jié)構(gòu)List作為存放選中數(shù)組元素結(jié)果的保存結(jié)構(gòu)。,15,例子2.2代理類型的應(yīng)用,usingSystem;usingSystem.Collection.Generic;classDelegates{publicdelegateboolNumPredicate(intnum);publicstaticvoidMain(){int[]number={1,2,3,4,5,6,7,8,9,10};NumPredicateevenPredicate=IsEven;Console.WriteLine(”CallIsevenusingadelegatevariable:{0}”,evenPredicate(4));ListevenNumbers=FilterArray(number,evenPredicate);,16,例子2.2代理類型的應(yīng)用(續(xù)1),DisplayList(“UseIsEventofilterevennumbers”,evenNumbers);ListoddNumbers=FilterArray(number,IsOdd);DisplayList(“UseIsOddtofilteroddnumbers:”,OddNumbers);ListNumberOver5=FilterArray(number,IsOver5);DisplayList(“UseIsOver5tofilternumbersover5:”,NumberOver5);}//endMainmethod,17,例子2.2(續(xù)2),privatestaticListFilterArray(int[]intAr,NumPredicatepred){Listresult=newList();foreach(intiteminintAr)if(pred(item))result.Add(item);returnresult;}//endmethodFilterArrayprivatestaticboolIsOdd(intnumber){return(number%2==1);}//endmethodIsOdd,18,例子2.2(續(xù)3),privatestaticboolIsEven(intnumber){return(number%2==0);}//endmethodIsEvenprivatestaticboolIsOver5(intnumber){return(number>5);}//endmethodIsOver5privatestaticvoidDisplayList(stringdescript,Listlist){Console.Write(descript);foreach(intiteminlist)Console.Write(“{0}“,item);Console.WriteLine();}}//endmethodDisplayList,19,例子2.2代理的應(yīng)用實(shí)例運(yùn)行結(jié)果,CallIsEvenusingadelegatevariable:TrueUseIsEventoFilterevennumbers:246810UseIsOddtoFilteroddnumbers:13579UseIsOver5toFilternumbersover5:678910,20,2.2對象初始化器,VisualStudioC#2008提供了一個新特性——對象初始化器(objectinitializer),它可以創(chuàng)建對象并在同一語句中將其屬性初始化。這適用于類沒有提供所需要的構(gòu)造函數(shù)的情況。采用初始化器時,不能寫與類同名的構(gòu)造方法,而是寫一個與類同名的初始化器,即原來構(gòu)造方法名字后面的圓括號“()”被一組花括號“{}”和類里面變量成員的初始值所代替。,21,對象初始化器的特點(diǎn),例如,Time1類的默認(rèn)構(gòu)造方法:Time1time=newTime1();采用初始化器時就變成:Time1time=newTime1{Hour=0,Minute=0,Second=0};采用初始化器時,類里面就不能編寫任何構(gòu)造方法。,22,例子2.3Time類的對象初始化器,publicclassTime{privateinthour;//0~23privateintminute;//0~59privateintsecond;//0~59publicvoidSetTime(inth,intm,ints){hour=((h>=0},23,例子2.3對象初始化器(續(xù)1),publicstringToUniversalString(){returnstring.Format(“{0:D2}:{1:D2}:{2:D2}”,hour,minute,second);}publicoverridestringToString(){returnstring.Format(“{0}:{1:D2}:{2:D2}{3}”,((hour==0||hour==12)?12:hour%12),hour,minute,second,(hour=0}}},25,例子2.3程序代碼(續(xù)3),usingSystem;publicclassObjectInitializerTest{publicstaticvoidMain(string[]args){Console.Write(“Timeobjectcreatedwithobjectinitializer“);Timetime=newTime{Hour=14,Minute=145,Second=12};Console.Write(“Standardtime{0}:“,time.ToString());Console.Write(“Universaltime{0}:“,time.ToUniversalString());Console.Write(“TimeobjectcreatedwithMinutepropertyset“);Timeanothertime=newTime{Minute=45};Console.Write(“Standardtime{0}:“,anothertime.ToString());Console.Write(“Universaltime{0}:“,anothertime.ToUniversalString());}},,26,例子2.3程序運(yùn)行結(jié)果:,TimeobjectcreatedwithobjectinitializerStandardtime:2:00:12PMUniversaltime:14:00:12TimeobjectcreatedwithMinutepropertysetStandardtime:12:45:00AMUniversaltime:00:45:00注意:每個屬性名只能在對象初始化器表中出現(xiàn)一次。對象初始化器按照每個參數(shù)出現(xiàn)的順序執(zhí)行屬性的初始化。如果對象初始化器中指定的值無效(如Minute=0145),則set方法強(qiáng)制設(shè)其為0。,27,集合初始化器,如果集合實(shí)現(xiàn)了泛型System.Collections.Generic-.ICollections接口,并且指定了T的類型,就可以使用集合初始化器來對整個集合初始化。集合初始化器將對集合中的每個元素調(diào)用ICollection.Add(T)方法,從而把該元素添加到集合中。集合初始化器由一系列包括花括號之間的元素初始化器構(gòu)成,元素初始化器之間使用逗號進(jìn)行分割。元素初始化器不能是賦值表達(dá)式。,28,例子2.4集合初始化器和對象初始化器的復(fù)合使用,usingSystem;usingSystem.Collections.Generic;namespaceDemoInitislizer{classGirlfriend//DemoObject{publicstringName{get;set;}publicintAge{get;set;}}classBoyfriend//DemoObject{publicstringName{get;set;}publicintAge{get;set;}publicListGirls{get;set;}//SetAttribute},29,例子2.4程序代碼(續(xù)),publicclassSetInitializerTest{publicstaticvoidMain(string[]args){Listgfs1=newList{“Mary”,“Susan”,”Lucy”};Listgfs2=newList();gfs2.Add(“Mary”);gfs2.Add(“Susan”);gfs2.Add(”Lucy”);Boyboy=newBoy{Name=“Tom”,Age=24,Girls=newList{newGirlfriend{Name=“Mary”,Age=23},newGirlfriend{Name=“Susan”,Age=19},newGirlfriend{Name=“Lucy”,Age=21}}};}}},30,例子2.4程序代碼的分析說明,本例中,對于gfs1就是用集合初始化器創(chuàng)建的它等價于gfs2對每一個元素分別調(diào)用元素初始化器ICollection.Add(T)方法。對Boy類的對象boy使用了對象初始化器與集合初始化器的復(fù)合使用,用一條語句完成了對多個對象和整個集合的初始化。,31,2.3匿名類型,匿名類型顧名思義就是沒有類的名稱,也就是沒有類的定義,但是它有類體,可以創(chuàng)建簡單類,用于存儲數(shù)據(jù)。匿名類型聲明也稱為匿名對象生成表達(dá)式,類似于初始化器,其聲明的開頭是關(guān)鍵字new,然后是成員初始化器列表,放在花括號中。在new后面是不能有類的構(gòu)造方法名(與類名相同)的。例如:varbob=new{Name=“BobSmith”,Age=26};聲明了一個匿名類對象bob,且其屬性Name=“BobSmith”,Age=26。注意這個類沒有類名。,32,例子2.5使用匿名類的例子,usingSystem;classAnonymousTypes{staticvoidMain(){varbob=new{Name=“BobSmith”,Age=37};Console.WriteLine(“Bob:”,bob.ToString());varsteve=new{Name=“SteveJones”,Age=26};Console.WriteLine(“Steve:”,steve.ToString());Console.WriteLine(“\nBobandSteveare{0}:”,(bob.Equals(steve)?“equal”:“notequal”));,33,例子2.5使用匿名類的例子(續(xù)),varbob2=new{Name=“BobSmith”,Age=37};Console.WriteLine(“\nBob2:”,bob2.ToString());Console.WriteLine(“\nBobandBob2are{0}:”,(bob.Equals(steve)?“equal”:“notequal”));}//endMainmethod},34,Bob:{Name=BobSmith,Age=37}Steve:{Name=SteveJones,Age=26}BobandStevearenotequalBob2:{Name=BobSmith,Age=37}BobandBob2areequal分析:上例中使用了隱式類型局部變量保存對匿名類型對象的引用,如varbob=new{Name=“BobSmith”,Age=37};還用匿名類型的方法ToString()在控制臺上顯示這個對象的信息。編譯器在創(chuàng)建匿名類型定義時定義ToString方法,它返回的字符串放在花括號中。例子中還創(chuàng)建了另一個匿名類對象Steve,其使用的初始化器內(nèi)容與bob的相同,被認(rèn)為相同類型。比較兩個匿名類對象相等,要檢查他們的所有屬性(這里是Name和Age),有其中一個不等,則兩個匿名類對象不相等。,34,例子2.5運(yùn)行結(jié)果,35,匿名類型的進(jìn)一步說明,匿名類型一般出現(xiàn)在ADO.NET的select子句中,用來投影篩選出的數(shù)據(jù)。匿名類型使用new運(yùn)算符和對象初始值設(shè)定項(xiàng)來創(chuàng)建。匿名類型創(chuàng)建的屬性是只讀的,匿名類型的名稱和屬性的數(shù)據(jù)類型由編譯器隨機(jī)指定或自動推斷。,36,匿名類型的進(jìn)一步說明,匿名類型不允許包含屬性以外的成員,不能強(qiáng)制轉(zhuǎn)換為Object以外的類型或接口,如果匿名類型賦值給變量,必須使用var關(guān)鍵字構(gòu)建此變量。多個匿名類型具有相同的順序、相同數(shù)量和種類的屬性成員,編譯器會將這些匿名類型視為相同的類型,并且它們共享編譯器生成的類型信息。,37,例子2.6匿名類型創(chuàng)建類,usingSystem;usingSystem.Linq;usingSystem.Collections.Generic;namespaceDemoAnonymousType{classProgram{publicstaticvoidMain(string[]args){varanonymous1=//創(chuàng)建匿名類型new{Name=“安碧茹”,Title=“苗族圣姑”,Age=36};varanonymous2=//創(chuàng)建匿名類型,類型同上new{Name=“寧雨昔”,Title=“圣坊仙子”,Age=37};Listlst=newList{“高麗公主”,“大華軍師”,“霓裳公主”};Console.WriteLine(“anonymous1的類型:{0}”,anonymous1.GetType().Name);Console.WriteLine(“{0}{1}{2}”,anonymous1.Name,anonymous1.Title,anonymous1.Age);,38,例子2.6匿名類型創(chuàng)建類(續(xù)),Console.WriteLine(“anonymous2的類型:{0}”,anonymous2.GetType().Name);Console.WriteLine(“{0}{1}{2}”,anonymous2.Name,anonymous2.Title,anonymous2.Age);Console.WriteLine(“********************”);varquery=fromninlst//LINQselect子句中創(chuàng)建匿名類型wheren.IndexOf(“公主”)>-1selectnew{Name=“查詢元素”,Title=n};//LINQ的select子句把查詢到的元素投影成匿名類型foreach(variteminquery){Console.WriteLine(“元素的類型:{0}”,item.GetType().Name);Console.WriteLine(“{0}{1}”,item.Name,item.Title);}}}},39,例子2.6匿名類型創(chuàng)建類的分析,本例用var定義的兩個匿名類型對象anonymous1、anonymous2由于屬性的類型、順序相同,所以這兩個匿名類型生成的類型也是一致的。本例在LINQ查詢中的的select子句也創(chuàng)建了一個匿名類型,其類型也與上面定義的兩個匿名對象的類型是一致的:selectnew{Name=“查詢元素”,Title=n};,40,例子2.6匿名類型創(chuàng)建類的運(yùn)行結(jié)果,,,anonymous1的類型:f_AnonymousType0’3安碧茹苗族圣姑36anonymous2的類型:_AnonymousType0’3寧雨昔圣坊仙子37*********************************************************元素的類型:f_AnonymousType1’2查詢元素高麗公主元素的類型:f_AnonymousType1’2查詢元素霓裳公主,41,2.4擴(kuò)展方法:對現(xiàn)有類增加新方法,有時需要在現(xiàn)有類里面增加新的功能或方法,但是由于受到一些限制又無法對這些類進(jìn)行修改。就可以利用類的擴(kuò)展方法在不必修改類的代碼的前提下為現(xiàn)有類增加新的功能。例如,Time類沒有顯示時間的方法,增加一個擴(kuò)展方法DisplayTime,它用Time對象的ToString方法在控制臺窗口中顯示時間。,42,擴(kuò)展方法的特點(diǎn)(續(xù)),新增的DisplayTime方法不必修改Time類的源代碼,關(guān)鍵是在其方法頭的參數(shù)表中的Time對象參數(shù)前面添加關(guān)鍵字this。關(guān)鍵字this告訴編譯器DisplayTime方法擴(kuò)展了現(xiàn)有類。C#編譯器將用這個信息把增加的代碼插入編譯的程序中,使得現(xiàn)有類型可以使用擴(kuò)展方法。具體實(shí)例參見下面的例子2.7。,43,擴(kuò)展方法的特點(diǎn),給已經(jīng)存在的類型添加方法,除了繼承類型外,就要采用擴(kuò)展方法了。擴(kuò)展方法是一種建立在非泛型、非嵌套的靜態(tài)類中特殊的靜態(tài)方法。調(diào)用擴(kuò)展方法與調(diào)用在類型中實(shí)際定義的方法之間沒有明顯的差異。擴(kuò)展方法是靜態(tài)方法,所以無法訪問類型的內(nèi)部成員。擴(kuò)展方法的第一個參數(shù)的數(shù)據(jù)類型,決定這個方法應(yīng)用于哪個類型,在其前面還需標(biāo)有this關(guān)鍵字。,44,例子2.7Time類的擴(kuò)展方法,usingSystem;classTimeExtensionsTest{staticvoidMain(string[]args){Timentime=newTime();ntime.SetTime(11,34,15);Console.Write(“UsetheDisplaymethod:“);ntime.DisplayTime();Console.Write(“Add5hourstotheTimeobject:”);,45,例子2.7Time類的擴(kuò)展方法(續(xù)),TimetimeAdded=ntime.AddHours(5);timeAdded.DisplayTime();Console.Write(“Add15hourstotheTimeobject:”);ntime.AddHours(15).DisplayTime();Console.Write(“Usefullyqualifiedextension-methodname:”);TimeExtension.DisplayTime(nTime);}},46,例子2.7程序代碼(續(xù)),staticclassTimeExtensions{publicstaticvoidDisplayTime(thisTimeaTime){Console.WriteLine(aTime.ToString());}publicstaticTimeAddHours(thisTimeaTime,inthours){TimenewTime=newTime();newTime.Minute=aTime.Minute;newTime.Second=aTime.Second;newTime.Hour=(aTime.Hours+hours)%24;returnnewTime.;}},47,例子2.7程序運(yùn)行結(jié)果,UsetheDisplaymethod:11:34:15AMAdd5hourstotheTimeobject:4:34:15PMAdd15hourstotheTimeobject:2:34:15AMUsefullyqualifiedextension-methodname:11:34:15AM,48,例子2.8擴(kuò)展方法的進(jìn)一步應(yīng)用,本例編寫一個把字符串類型變量s通過調(diào)用一個轉(zhuǎn)換方法ToInt,轉(zhuǎn)換成數(shù)字的程序。由于在字符串類型中沒有這個方法,而字符串類型已經(jīng)是系統(tǒng)直接定義好的,故采取擴(kuò)展方法技術(shù)增加這個方法,使用起來就像ToInt方法是String類型的一個實(shí)例方法一樣。例如:Strings=“200”;inti=s.ToInt();,49,例子2.8擴(kuò)展方法的應(yīng)用(續(xù)),但是,實(shí)例方法只能通過一個類的實(shí)例(對象)來調(diào)用,不能直接通過類名來調(diào)用。而靜態(tài)方法則只能通過類名來調(diào)用。例如,String類型的ToUpper方法就是一個實(shí)例方法,只能在一個String類型的對象上被調(diào)用,如:stringname=“Joe”;Console.WriteLine(name.ToUpper());,50,例子2.8擴(kuò)展方法的應(yīng)用實(shí)例,usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespaceDemoExtensionMethods{publicstaticclassEMClass{publicststicintToInt(thisstrings){returnInt32.Parse(s);}}classProgram{staticvoidMain(string[]args){strings=“200”;inti=s.ToInt();//調(diào)用擴(kuò)展方法,無需傳遞參數(shù)Console.WriteLine(i);}}},51,例子2.8的程序代碼說明,本例代碼首先定義了一個靜態(tài)類EMClass,在類的內(nèi)部定義了一個靜態(tài)方法ToInt,注意該方法的定義參數(shù)有一個this關(guān)鍵字(擴(kuò)展方法可以有多個參數(shù),但是只有第一個參數(shù)能被this修飾,表示它代表要被擴(kuò)展的類型,這里是String),該方法實(shí)現(xiàn)的邏輯是將字符串轉(zhuǎn)換為整數(shù);接下來在Main方法中生成一個字符串,在此實(shí)例對象上調(diào)用方法ToInt得到轉(zhuǎn)換后的數(shù)字結(jié)果“200”并在屏幕上打印顯示出來。,52,2.5泛型,目前主流的編程語言中,大部分是強(qiáng)類型編程語言,即要求變量或?qū)ο蟊仨氂凶约旱念愋?,不同類型之間的轉(zhuǎn)換還要遵守嚴(yán)格規(guī)則。強(qiáng)類型編程語言有助于編寫更加安全的程序代碼,但是其通用性方面還有欠缺??紤]下面求2個整數(shù)中的較小者:intMin(inta,intb){if(a(No%2==0);在lambda表達(dá)式No%2==0中,用運(yùn)算符%確定參數(shù)No值是不是偶數(shù)。表達(dá)式產(chǎn)生的真假值由lambda表達(dá)式隱式返回。lambda表達(dá)式不用指定返回值,返回類型可以從返回值或代理的返回值推定。,60,C#Lambda表達(dá)式來源,Lambda實(shí)際上源遠(yuǎn)流長,現(xiàn)在使用的機(jī)器都是馮-諾依曼體系的,屬于圖靈機(jī),在那之前還有一種稱作λ演算的理論,但是圖靈機(jī)由于先被實(shí)現(xiàn)出來,所以大行其道,λ演算后來成就了函數(shù)式編程語言特別是Lisp,在函數(shù)式編程語言里函數(shù)是第一等元素,函數(shù)的參數(shù),函數(shù)的返回值都是函數(shù),程序沒有變量,函數(shù)嵌套函數(shù)。而且函數(shù)式編程語言一直存在于象牙塔中,在工業(yè)界沒有流行。但近年來工業(yè)界比較喜歡“復(fù)古”風(fēng)格,而函數(shù)式編程語言能解決一些命令式編程難以解決的問題(或者解決起來非常麻煩),所以也走上了歷史舞臺。C#要做到函數(shù)風(fēng)格編程怎么辦?靠原來的方法定義的方式肯定不行,2.0的匿名方法初步解決了這個問題,但還不夠,3.0的Lambda終于很好的解決了,一個Lambda就是一個delegate,一個delegate指向一個方法,現(xiàn)在我們使用Lambda也能簡單的將方法作為參數(shù)傳遞了,還可以層層嵌套,簡化了編程。,61,Lambda表達(dá)式本質(zhì),lambda是一個匿名方法,其本質(zhì)上是匿名方法在語法上的簡化,匿名方法具備的特性,lambda表達(dá)式也同樣具備。它可以包含表達(dá)式和語句,并且可用于創(chuàng)建委托或表達(dá)式樹類型。使用lambda表達(dá)式是在C#2.0推出的匿名方法的特性基礎(chǔ)上,將匿名方法的語法進(jìn)一步簡化。另外,lambda表達(dá)式還通過使用表達(dá)式樹推遲代碼的編譯時間,使得代碼可以在系統(tǒng)運(yùn)行時動態(tài)編譯,增加代碼的靈活性。lambda表達(dá)式主要用于代替匿名方法,以更簡潔的方式向方法中加入一些短小的代碼片段。,62,Lambda表達(dá)式對匿名方法的改進(jìn),先看一下匿名方法的使用。在.net2.0中System.Collections.-Generic命名空間下List里有一些新增的方法。比如Find,若使用匿名方法可寫為:books.Find(delegate(Bookbook){returnbook.Pricebook.Pricex+1//后面跟著表達(dá)式Deleage(intx){returnx+1;}//后面跟著語句塊x=>{returnx+1;}//后面跟著語句塊Delegate(intx){returnx+1;}//輸入?yún)?shù)也可以帶類型(intx)=>x+1//后面跟著表達(dá)式Delegate(intx){returnx+1;}//可輸入多個參數(shù),逗號分隔(x,y)=>x+y//后面跟著表達(dá)式Delegate(intx,inty){returnx+y;}//無參的也行()=>1//無參數(shù),后跟表達(dá)式Delegate(){return1;},64,Lambda表達(dá)式和語句,Lambda表達(dá)式的形式如下:(inputparameter)=>expressionlambda使用lambda運(yùn)算符=>,運(yùn)算符的左邊是可選的輸入?yún)?shù),右邊是表達(dá)式。該運(yùn)算符與賦值運(yùn)算符優(yōu)先級相同,也是右結(jié)合運(yùn)算符。Lambda語句的形式如下:(inputparameter)=>{statement;}Lambda的語句與表達(dá)式基本一樣,只是運(yùn)算符“=>”右面使用花括號包含的代碼快。,65,例子2.10創(chuàng)建lambda表達(dá)式,usingSystem;namespaceDemolambda{classProgram{delegatestringMyDelegate(stringt,stringn);staticvoidMain(string[]args){MyDelegatedele=(t,n)=>//定義lambda表達(dá)式string.Format(“{0}{1}”,t,n);Console.WriteLine(“調(diào)用lambda表達(dá)式\n”);Console.WriteLine(dele(“Doctor”,“John”));Console.WriteLine(dele(“Sir”,“Tomson”));Console.WriteLine(dele(“Ms”,“Kathy”));Console.WriteLine(“\n*******************************\n”);,66,例子2.10程序代碼(續(xù)),stringtmp=“這里是lambda語句外的變量“;MyDelegatedele2=(t,n)=>//定義lambda語句{Console.WriteLine(“從Lambda語句體中輸出”);Console.WriteLine(“輸出外部變量tmp:{0}”,tmp);strings;s=string.Format(”{0}{1}小姐“,t,n);returns;};Console.WriteLine(“調(diào)用Lambda語句\n”);Console.WriteLine(dele2(“Ms”,“Kathy”));}}},67,例子2.11lambda表達(dá)式的應(yīng)用,usingSystem;usingSystem.Collection.Generic;classLambda{publicdelegateboolNumPredicate(intnum);publicstaticvoidMain(){int[]number={1,2,3,4,5,6,7,8,9,10};NumPredicateevenPredicate=num=>(num%2==0);Console.WriteLine(”Usealambda-expressionvariable:{0}”,evenPredicate(4));ListevenNumbers=FilterArray(number,evenPredicate);DisplayList(”Usealambda-expressiontofilterevennumbers:”,evenNumbers);ListoddNumbers=FilterArray(number,(intnum)=>(num%2==1));DisplayList(”Usealambda-expressiontofilteroddnumbers:”,OddNumbers);ListNumberOver5=FilterArray(number,num=>{returnnum>5;});DisplayList(”Usealambda-expressiontofilternumbersover5:”,NumberOver5);}//endMainmethod,68,例子2.11程序代碼(續(xù)),privatestaticListFilterArray(int[]intAr,NumPredicatepred){Listresult=newList();foreach(intiteminintAr)if(pred(item))result.Add(item);returnresult;}//endmethodFilterArrayprivatestaticvoidDisplayList(stringdescript,Listlist){Console.Write(descript);foreach(intiteminlist)Console.Write(“{0}“,item);Console.WriteLine();}}//endmethodDisplayList,69,例子2.11的運(yùn)行結(jié)果,Usealambda-expressionvariable:TrueUsealambda-expressiontofilterevennumbers:246810Usealambda-expressiontofilteroddnumbers:13579Usealambda-expressiontofilternumbersover5:678910,70,Lambda表達(dá)式樹,Lambda表達(dá)式樹是Lambda表達(dá)式以樹的形式表現(xiàn)出來的另外一種數(shù)據(jù)結(jié)構(gòu)。一個表達(dá)式樹是一個System.Linq.Expressions.Expression泛型的實(shí)例,委托類型T是與此表達(dá)式樹相對應(yīng)的lambda表達(dá)式的委托類型(System.Linq命名空間中對應(yīng)的Func類型)。并不是所有的lambda表達(dá)式都可以被轉(zhuǎn)換為表達(dá)式樹,只有那些只包含表達(dá)式主體內(nèi)容的lambda表達(dá)式(如(a,b)=>a+b)才可以被轉(zhuǎn)換。如果在主體中包含了聲明性質(zhì)的語句,則不能被轉(zhuǎn)換。,71,例子2.12lambda表達(dá)式樹的應(yīng)用,usingSystem;usingSystem.Linq.Expressions;namespaceDemoLambda{publicclassProgram{publicstaticvoidMain(string[]args){Expression>tree=n=>168;//定義表達(dá)式目錄樹BinaryExpressionbody=(BinaryExpression)tree.168;ParameterExpressionleft=(ParameterExpression)body.Left;ConstantExpressionright=(ConstantExpression)body.Right;Console.WriteLine(“分解結(jié)果:{0}{1}{2}\n”,//分解結(jié)果left.Name,body.NodeType,right.Value);Funct=tree.Compile();//編譯目錄樹Console.WriteLine(“1000是否大于168:{0}“,t(1000));}}},72,例子2.12程序代碼和運(yùn)行結(jié)果,Lambda表達(dá)式樹負(fù)責(zé)分解、優(yōu)化Lambda表達(dá)式,實(shí)際應(yīng)用的機(jī)會不太多。結(jié)果如下:,73,2.7枚舉量和Yield,枚舉用于由有限多個選擇情況構(gòu)成的場合,枚舉類型為一組符號常數(shù)提供了一個用戶自己定義的類型名稱。在枚舉中的每個成員實(shí)際上是一個符號常數(shù)。當(dāng)對有限多個選擇依次進(jìn)行循環(huán)操作時,要求操作后返回到循環(huán)開始處以便進(jìn)行下一次循環(huán)操作,而不是到return語句之后的語句繼續(xù)執(zhí)行,這就要使用到y(tǒng)ield關(guān)鍵字。,74,2.7.1枚舉類型—enum,只要將需要的變量值一一列舉出來,便構(gòu)成了一個枚舉類型。枚舉類型的聲明形式如下:enum枚舉類型名{變量值列表};例如:enumweekday{sun,mon,tue,wed,thu,fri,sat};它聲明了一個枚舉類型weekday,表示有sun,mon到sat的可能的七種情況,這七個單詞分別對應(yīng)了數(shù)字0,1,…,6。,75,枚舉類型—enum,枚舉類型應(yīng)用說明:對枚舉元素按常量處理,不能對它們賦值。例如,不能寫:sun=0;枚舉元素具有默認(rèn)值,它們依次為:0,1,2,......。也可以在聲明時另行指定枚舉元素的值,如:enumweekday{sun=7,mon=1,tue,wed,thu,fri,sat};枚舉值可以進(jìn)行關(guān)系運(yùn)算。整數(shù)值不能直接賦給枚舉變量,如需要將整數(shù)賦值給枚舉變量,應(yīng)進(jìn)行強(qiáng)制類型轉(zhuǎn)換。,76,枚舉成員的數(shù)值,一個枚舉成員的數(shù)值,既可以使用等號“=”顯示地賦值,也可以使用隱式賦值。對于隱式賦值按照以下的規(guī)則來確定值:——對第一個枚舉成員,如果沒有顯式賦值,則其被隱式賦予數(shù)值為0;——對于其它枚舉成員,如果沒有顯式賦值,它的數(shù)值被隱式地賦為前一枚舉成員的值加1;例如enumColor{red,green=10,blue,Max=blue}其中,red的值為0,green的值為10,blue的值為11,Max的值為11。,77,例子2.13枚舉應(yīng)用于體育比賽,設(shè)某次體育比賽的結(jié)果有四種可能:勝(win)、負(fù)(lose)、平局(tie)、比賽取消(cancel),編寫程序順序輸出這四種情況。分析:由于比賽結(jié)果只有四種可能,所以可以聲明一個枚舉類型,并聲明一個枚舉類型的變量來存放比賽結(jié)果。,78,usingSystem;publicclassEnumTest{publicstaticvoidMain(){enumgame_result{WIN,LOSE,TIE,CANCEL};game_resultresult;enumgame_resultomit=CANCEL;for(intcount=WIN;count0){_counter--;returntrue;}elsereturnfalse;}publicvoidReset(){_counter=_countdown.StartCountdown;}publicobjectCurrent{get{return_counter;}}//當(dāng)代碼段使用CountdownEnumerator時,才產(chǎn)生枚舉,84,例子2.14枚舉類的應(yīng)用(續(xù)2),publicclassDemoEnumerator{publicstaticvoidDemoCountdown(){Countdowncountdown=newCountdown();countdown.StartCountdown=5;IEnumeratorI=countdown.GetEnumberator();while(i.MoveNext()){intn=(int)i.Current;Console.WriteLine(n);}i.Reset();while(i.Reset()){intn=(int)i.Current;Console.WriteLine(“{0}BIS”,n);}}},85,迭代器與yield關(guān)鍵字,yield關(guān)鍵字在迭代器中,用于向枚舉對象返回元素值或發(fā)出迭代結(jié)束信號。yield關(guān)鍵字的使用形式如下:yieldreturn;yieldbreak;yield關(guān)鍵字只能用在定義迭代器的代碼塊中,yieldreturn返回枚舉元素后,會保存迭代器的枚舉位置,當(dāng)下次調(diào)用迭代器時,從保存的位置繼續(xù)執(zhí)行。,86,例子2.15使用yield關(guān)鍵字的迭代器,微軟從C#的高級版本2.0后,使用了簡潔的迭代器foreach代替過去只適用于簡單類型的循環(huán)控制語句,如for和while。配合yield關(guān)鍵字,用極少量的代碼,就可以構(gòu)造一個迭代器,實(shí)現(xiàn)過去用for和while等語句很難實(shí)現(xiàn)的對各類對象的循環(huán)控制。迭代器在C#中應(yīng)用廣泛,yield關(guān)鍵字在迭代器中向枚舉對象返回元素值或發(fā)出迭代結(jié)束信號。,87,例子2.15程序代碼(1),usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;namespaceDemoIterator1{///包含迭代器的自定義集合類publicclassMyDocuments:IEnumerable{privateListdocs=newList();publicvoidAdd(strings){docs.Add(s);}#regionIEnumerable成員publicIEnumeratorGetEnumerator(){foreach(stringsindocs){yieldreturns;}}#endregion},88,例子2.15程序代碼(2),classProgram{staticvoidMain- 1.請仔細(xì)閱讀文檔,確保文檔完整性,對于不預(yù)覽、不比對內(nèi)容而直接下載帶來的問題本站不予受理。
- 2.下載的文檔,不會出現(xiàn)我們的網(wǎng)址水印。
- 3、該文檔所得收入(下載+內(nèi)容+預(yù)覽)歸上傳者、原創(chuàng)作者;如果您是本文檔原作者,請點(diǎn)此認(rèn)領(lǐng)!既往收益都?xì)w您。
下載文檔到電腦,查找使用更方便
14.9 積分
下載 |
- 配套講稿:
如PPT文件的首頁顯示word圖標(biāo),表示該P(yáng)PT已包含配套word講稿。雙擊word圖標(biāo)可打開word文檔。
- 特殊限制:
部分文檔作品中含有的國旗、國徽等圖片,僅作為作品整體效果示例展示,禁止商用。設(shè)計(jì)者僅對作品中獨(dú)創(chuàng)性部分享有著作權(quán)。
- 關(guān) 鍵 詞:
- 技術(shù)設(shè)計(jì) 應(yīng)用 NET 第二
鏈接地址:http://www.3dchina-expo.com/p-3219629.html