臺(tái)技術(shù)設(shè)計(jì)與應(yīng)用NET第二章V.ppt
《臺(tái)技術(shù)設(shè)計(jì)與應(yīng)用NET第二章V.ppt》由會(huì)員分享,可在線閱讀,更多相關(guān)《臺(tái)技術(shù)設(shè)計(jì)與應(yīng)用NET第二章V.ppt(99頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
1,電子政務(wù)平臺(tái)技術(shù)設(shè)計(jì)與應(yīng)用,南大濱海學(xué)院法政學(xué)系張一鳴,電子政務(wù)平臺(tái)技術(shù)設(shè)計(jì)與應(yīng)用——ASP.NET高級(jí)應(yīng)用Version2,南大濱海學(xué)院法政學(xué)系張一鳴2016年2月10日,2,ASP.NET高級(jí)應(yīng)用第2章C#語(yǔ)言相關(guān)特性,南大濱海學(xué)院法政學(xué)系張一鳴2016年2月10日,電子政務(wù)平臺(tái)技術(shù)設(shè)計(jì)與應(yīng)用,3,本章主要內(nèi)容,本章主要是回顧和深入介紹在ASP.NET中涉及的C#中高級(jí)知識(shí),包括泛型、匿名、lambda表達(dá)式、yield關(guān)鍵字、IEnumerable接口等。,,,,,,委托,,,對(duì)象初始化表達(dá)式,匿名與匿名方法,Lambda表達(dá)式,,,,,泛型,擴(kuò)展方法,,,枚舉量和Yield,,,查詢(xún)表達(dá)式,4,C#的新特征,對(duì)于使用ASP.NET的復(fù)雜功能來(lái)說(shuō),它完全依賴(lài)與C#中新增的一些概念和特征,因此可以說(shuō),泛型等概念和特征是這些應(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ù)分為按值、按引用或按輸出等類(lèi)型。其中引用實(shí)際上就是原來(lái)變量即實(shí)參的別名,指向?qū)崊⒃趦?nèi)存中的位置,所以在方法中對(duì)引用類(lèi)型參數(shù)的修改會(huì)導(dǎo)致對(duì)實(shí)參本身的改變。類(lèi)似地,如果把方法也看成數(shù)據(jù),通過(guò)代理機(jī)制把方法賦值給一個(gè)變量,也就是把這個(gè)方法在內(nèi)存中的位置賦給變量,則通過(guò)這個(gè)變量就可以把這個(gè)方法傳遞給其他的方法調(diào)用。這種類(lèi)型的變量就是代理類(lèi)型的變量。,6,代理(委托)的實(shí)質(zhì),代理本身是一個(gè)類(lèi),它封裝了一個(gè)或多個(gè)方法。在內(nèi)部,一個(gè)代理保存方法指針(地址)的對(duì)照表,即這個(gè)代理類(lèi)里面的每個(gè)方法名和它對(duì)應(yīng)的地址的列表。每個(gè)方法指針可以與一個(gè)引用實(shí)例配對(duì),而該實(shí)例是包含實(shí)例方法的類(lèi)實(shí)例。聲明代理類(lèi)型時(shí)在方法頭前面放上關(guān)鍵字delegate,例如:publicdelegatevoidPrintCallback(intno);,7,例子2.1代理的應(yīng)用實(shí)例分析,本例是文書(shū)自動(dòng)回信的局部功能演示。根據(jù)輸入的來(lái)信人姓名和性別,確定增加“先生”或“女士”的稱(chēng)呼;根據(jù)處理來(lái)信時(shí)間,確定增加“你好”、“上午好”或“下午好”的問(wèn)候語(yǔ)。這需要編制添加稱(chēng)呼詞的兩個(gè)方法和添加時(shí)間問(wèn)候詞的三個(gè)方法。為了在主程序中使代碼簡(jiǎn)潔清晰,不用if語(yǔ)句分情況調(diào)用不同稱(chēng)呼詞和問(wèn)候語(yǔ)的辦法,而是采用兩個(gè)代理分別表示添加的內(nèi)容,問(wèn)候語(yǔ)的區(qū)別通過(guò)代理的參數(shù)來(lái)解決。,8,例子2.1代理類(lèi)型的應(yīng)用,usingSystem;NamespaceDemoDelegate1{delegatevoidmyDelegate(strings);//無(wú)返回類(lèi)型//的代理,添加問(wèn)候詞delegatestringmyDelegateStr(strings,boolman);//有返回類(lèi)型的代理,添加稱(chēng)呼詞classProgram{staticvoidshow1(strings){Console.WriteLine(“你好,{0}!”,s);}staticvoidshow2(strings){Console.WriteLine(“上午好,{0}!”,s);},9,例子2.1代理類(lèi)型的應(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(“返回帶類(lèi)型的綁定調(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)用上午好,林晚榮!下午好,林晚榮!**************************************返回類(lèi)型的代理調(diào)用你好,林晚榮先生!你好,徐芷晴女士!,13,例子2.2代理的應(yīng)用實(shí)例分析,本例是對(duì)一個(gè)有10個(gè)元素的整形數(shù)組,分別調(diào)用三個(gè)不同的方法過(guò)濾選出其偶數(shù)、奇數(shù)和大于5的數(shù)的子集并顯示。為了實(shí)現(xiàn)這個(gè)目的,一般是分別編寫(xiě)篩選偶數(shù)的方法IsEven、篩選奇數(shù)的方法IsOdd和篩選大于5的數(shù)的方法IsOver5,然后在程序里分別調(diào)用它們來(lái)實(shí)現(xiàn)要求。更簡(jiǎn)潔的辦法是采用代理技術(shù),設(shè)計(jì)一個(gè)代理類(lèi)型NumPredicate和它的實(shí)例對(duì)象變量even-Predicate。在主程序每次執(zhí)行不同的任務(wù)時(shí),都是調(diào)用同一個(gè)代理變量,只是分別給這個(gè)代理型變量賦值引用不同的方法。,14,例子2.2代理的應(yīng)用實(shí)例分析(續(xù)),IsEven、IsOdd和IsOver5這三個(gè)方法都接收一個(gè)整型參數(shù)int并判斷是否滿足條件,然后返回一個(gè)布爾型邏輯值。為了解決對(duì)數(shù)組全部元素過(guò)濾挑選的任務(wù),又設(shè)計(jì)了一個(gè)方法FilterArray,它接受待過(guò)濾的數(shù)組和代理類(lèi)型NumPredicate的引用變量作為參數(shù),并按照每次引用變量所指向的方法對(duì)數(shù)組進(jìn)行具體的過(guò)濾操作。對(duì)每次選中的結(jié)果調(diào)用方法DisplayList全部顯示出來(lái)。本例中采用了列表結(jié)構(gòu)List作為存放選中數(shù)組元素結(jié)果的保存結(jié)構(gòu)。,15,例子2.2代理類(lèi)型的應(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代理類(lèi)型的應(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對(duì)象初始化器,VisualStudioC#2008提供了一個(gè)新特性——對(duì)象初始化器(objectinitializer),它可以創(chuàng)建對(duì)象并在同一語(yǔ)句中將其屬性初始化。這適用于類(lèi)沒(méi)有提供所需要的構(gòu)造函數(shù)的情況。采用初始化器時(shí),不能寫(xiě)與類(lèi)同名的構(gòu)造方法,而是寫(xiě)一個(gè)與類(lèi)同名的初始化器,即原來(lái)構(gòu)造方法名字后面的圓括號(hào)“()”被一組花括號(hào)“{}”和類(lèi)里面變量成員的初始值所代替。,21,對(duì)象初始化器的特點(diǎn),例如,Time1類(lèi)的默認(rèn)構(gòu)造方法:Time1time=newTime1();采用初始化器時(shí)就變成:Time1time=newTime1{Hour=0,Minute=0,Second=0};采用初始化器時(shí),類(lèi)里面就不能編寫(xiě)任何構(gòu)造方法。,22,例子2.3Time類(lèi)的對(duì)象初始化器,publicclassTime{privateinthour;//0~23privateintminute;//0~59privateintsecond;//0~59publicvoidSetTime(inth,intm,ints){hour=((h>=0},23,例子2.3對(duì)象初始化器(續(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注意:每個(gè)屬性名只能在對(duì)象初始化器表中出現(xiàn)一次。對(duì)象初始化器按照每個(gè)參數(shù)出現(xiàn)的順序執(zhí)行屬性的初始化。如果對(duì)象初始化器中指定的值無(wú)效(如Minute=0145),則set方法強(qiáng)制設(shè)其為0。,27,集合初始化器,如果集合實(shí)現(xiàn)了泛型System.Collections.Generic-.ICollections接口,并且指定了T的類(lèi)型,就可以使用集合初始化器來(lái)對(duì)整個(gè)集合初始化。集合初始化器將對(duì)集合中的每個(gè)元素調(diào)用ICollection.Add(T)方法,從而把該元素添加到集合中。集合初始化器由一系列包括花括號(hào)之間的元素初始化器構(gòu)成,元素初始化器之間使用逗號(hào)進(jìn)行分割。元素初始化器不能是賦值表達(dá)式。,28,例子2.4集合初始化器和對(duì)象初始化器的復(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程序代碼的分析說(shuō)明,本例中,對(duì)于gfs1就是用集合初始化器創(chuàng)建的它等價(jià)于gfs2對(duì)每一個(gè)元素分別調(diào)用元素初始化器ICollection.Add(T)方法。對(duì)Boy類(lèi)的對(duì)象boy使用了對(duì)象初始化器與集合初始化器的復(fù)合使用,用一條語(yǔ)句完成了對(duì)多個(gè)對(duì)象和整個(gè)集合的初始化。,31,2.3匿名類(lèi)型,匿名類(lèi)型顧名思義就是沒(méi)有類(lèi)的名稱(chēng),也就是沒(méi)有類(lèi)的定義,但是它有類(lèi)體,可以創(chuàng)建簡(jiǎn)單類(lèi),用于存儲(chǔ)數(shù)據(jù)。匿名類(lèi)型聲明也稱(chēng)為匿名對(duì)象生成表達(dá)式,類(lèi)似于初始化器,其聲明的開(kāi)頭是關(guān)鍵字new,然后是成員初始化器列表,放在花括號(hào)中。在new后面是不能有類(lèi)的構(gòu)造方法名(與類(lèi)名相同)的。例如:varbob=new{Name=“BobSmith”,Age=26};聲明了一個(gè)匿名類(lèi)對(duì)象bob,且其屬性Name=“BobSmith”,Age=26。注意這個(gè)類(lèi)沒(méi)有類(lèi)名。,32,例子2.5使用匿名類(lèi)的例子,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使用匿名類(lèi)的例子(續(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分析:上例中使用了隱式類(lèi)型局部變量保存對(duì)匿名類(lèi)型對(duì)象的引用,如varbob=new{Name=“BobSmith”,Age=37};還用匿名類(lèi)型的方法ToString()在控制臺(tái)上顯示這個(gè)對(duì)象的信息。編譯器在創(chuàng)建匿名類(lèi)型定義時(shí)定義ToString方法,它返回的字符串放在花括號(hào)中。例子中還創(chuàng)建了另一個(gè)匿名類(lèi)對(duì)象Steve,其使用的初始化器內(nèi)容與bob的相同,被認(rèn)為相同類(lèi)型。比較兩個(gè)匿名類(lèi)對(duì)象相等,要檢查他們的所有屬性(這里是Name和Age),有其中一個(gè)不等,則兩個(gè)匿名類(lèi)對(duì)象不相等。,34,例子2.5運(yùn)行結(jié)果,35,匿名類(lèi)型的進(jìn)一步說(shuō)明,匿名類(lèi)型一般出現(xiàn)在ADO.NET的select子句中,用來(lái)投影篩選出的數(shù)據(jù)。匿名類(lèi)型使用new運(yùn)算符和對(duì)象初始值設(shè)定項(xiàng)來(lái)創(chuàng)建。匿名類(lèi)型創(chuàng)建的屬性是只讀的,匿名類(lèi)型的名稱(chēng)和屬性的數(shù)據(jù)類(lèi)型由編譯器隨機(jī)指定或自動(dòng)推斷。,36,匿名類(lèi)型的進(jìn)一步說(shuō)明,匿名類(lèi)型不允許包含屬性以外的成員,不能強(qiáng)制轉(zhuǎn)換為Object以外的類(lèi)型或接口,如果匿名類(lèi)型賦值給變量,必須使用var關(guān)鍵字構(gòu)建此變量。多個(gè)匿名類(lèi)型具有相同的順序、相同數(shù)量和種類(lèi)的屬性成員,編譯器會(huì)將這些匿名類(lèi)型視為相同的類(lèi)型,并且它們共享編譯器生成的類(lèi)型信息。,37,例子2.6匿名類(lèi)型創(chuàng)建類(lèi),usingSystem;usingSystem.Linq;usingSystem.Collections.Generic;namespaceDemoAnonymousType{classProgram{publicstaticvoidMain(string[]args){varanonymous1=//創(chuàng)建匿名類(lèi)型new{Name=“安碧茹”,Title=“苗族圣姑”,Age=36};varanonymous2=//創(chuàng)建匿名類(lèi)型,類(lèi)型同上new{Name=“寧雨昔”,Title=“圣坊仙子”,Age=37};Listlst=newList{“高麗公主”,“大華軍師”,“霓裳公主”};Console.WriteLine(“anonymous1的類(lèi)型:{0}”,anonymous1.GetType().Name);Console.WriteLine(“{0}{1}{2}”,anonymous1.Name,anonymous1.Title,anonymous1.Age);,38,例子2.6匿名類(lèi)型創(chuàng)建類(lèi)(續(xù)),Console.WriteLine(“anonymous2的類(lèi)型:{0}”,anonymous2.GetType().Name);Console.WriteLine(“{0}{1}{2}”,anonymous2.Name,anonymous2.Title,anonymous2.Age);Console.WriteLine(“********************”);varquery=fromninlst//LINQselect子句中創(chuàng)建匿名類(lèi)型wheren.IndexOf(“公主”)>-1selectnew{Name=“查詢(xún)?cè)亍?Title=n};//LINQ的select子句把查詢(xún)到的元素投影成匿名類(lèi)型foreach(variteminquery){Console.WriteLine(“元素的類(lèi)型:{0}”,item.GetType().Name);Console.WriteLine(“{0}{1}”,item.Name,item.Title);}}}},39,例子2.6匿名類(lèi)型創(chuàng)建類(lèi)的分析,本例用var定義的兩個(gè)匿名類(lèi)型對(duì)象anonymous1、anonymous2由于屬性的類(lèi)型、順序相同,所以這兩個(gè)匿名類(lèi)型生成的類(lèi)型也是一致的。本例在LINQ查詢(xún)中的的select子句也創(chuàng)建了一個(gè)匿名類(lèi)型,其類(lèi)型也與上面定義的兩個(gè)匿名對(duì)象的類(lèi)型是一致的:selectnew{Name=“查詢(xún)?cè)亍?Title=n};,40,例子2.6匿名類(lèi)型創(chuàng)建類(lèi)的運(yùn)行結(jié)果,,,anonymous1的類(lèi)型:f_AnonymousType0’3安碧茹苗族圣姑36anonymous2的類(lèi)型:_AnonymousType0’3寧雨昔圣坊仙子37*********************************************************元素的類(lèi)型:f_AnonymousType1’2查詢(xún)?cè)馗啕惞髟氐念?lèi)型:f_AnonymousType1’2查詢(xún)?cè)啬奚压?41,2.4擴(kuò)展方法:對(duì)現(xiàn)有類(lèi)增加新方法,有時(shí)需要在現(xiàn)有類(lèi)里面增加新的功能或方法,但是由于受到一些限制又無(wú)法對(duì)這些類(lèi)進(jìn)行修改。就可以利用類(lèi)的擴(kuò)展方法在不必修改類(lèi)的代碼的前提下為現(xiàn)有類(lèi)增加新的功能。例如,Time類(lèi)沒(méi)有顯示時(shí)間的方法,增加一個(gè)擴(kuò)展方法DisplayTime,它用Time對(duì)象的ToString方法在控制臺(tái)窗口中顯示時(shí)間。,42,擴(kuò)展方法的特點(diǎn)(續(xù)),新增的DisplayTime方法不必修改Time類(lèi)的源代碼,關(guān)鍵是在其方法頭的參數(shù)表中的Time對(duì)象參數(shù)前面添加關(guān)鍵字this。關(guān)鍵字this告訴編譯器DisplayTime方法擴(kuò)展了現(xiàn)有類(lèi)。C#編譯器將用這個(gè)信息把增加的代碼插入編譯的程序中,使得現(xiàn)有類(lèi)型可以使用擴(kuò)展方法。具體實(shí)例參見(jiàn)下面的例子2.7。,43,擴(kuò)展方法的特點(diǎn),給已經(jīng)存在的類(lèi)型添加方法,除了繼承類(lèi)型外,就要采用擴(kuò)展方法了。擴(kuò)展方法是一種建立在非泛型、非嵌套的靜態(tài)類(lèi)中特殊的靜態(tài)方法。調(diào)用擴(kuò)展方法與調(diào)用在類(lèi)型中實(shí)際定義的方法之間沒(méi)有明顯的差異。擴(kuò)展方法是靜態(tài)方法,所以無(wú)法訪問(wèn)類(lèi)型的內(nèi)部成員。擴(kuò)展方法的第一個(gè)參數(shù)的數(shù)據(jù)類(lèi)型,決定這個(gè)方法應(yīng)用于哪個(gè)類(lèi)型,在其前面還需標(biāo)有this關(guān)鍵字。,44,例子2.7Time類(lèi)的擴(kuò)展方法,usingSystem;classTimeExtensionsTest{staticvoidMain(string[]args){Timentime=newTime();ntime.SetTime(11,34,15);Console.Write(“UsetheDisplaymethod:“);ntime.DisplayTime();Console.Write(“Add5hourstotheTimeobject:”);,45,例子2.7Time類(lèi)的擴(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)用,本例編寫(xiě)一個(gè)把字符串類(lèi)型變量s通過(guò)調(diào)用一個(gè)轉(zhuǎn)換方法ToInt,轉(zhuǎn)換成數(shù)字的程序。由于在字符串類(lèi)型中沒(méi)有這個(gè)方法,而字符串類(lèi)型已經(jīng)是系統(tǒng)直接定義好的,故采取擴(kuò)展方法技術(shù)增加這個(gè)方法,使用起來(lái)就像ToInt方法是String類(lèi)型的一個(gè)實(shí)例方法一樣。例如:Strings=“200”;inti=s.ToInt();,49,例子2.8擴(kuò)展方法的應(yīng)用(續(xù)),但是,實(shí)例方法只能通過(guò)一個(gè)類(lèi)的實(shí)例(對(duì)象)來(lái)調(diào)用,不能直接通過(guò)類(lèi)名來(lái)調(diào)用。而靜態(tài)方法則只能通過(guò)類(lèi)名來(lái)調(diào)用。例如,String類(lèi)型的ToUpper方法就是一個(gè)實(shí)例方法,只能在一個(gè)String類(lèi)型的對(duì)象上被調(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ò)展方法,無(wú)需傳遞參數(shù)Console.WriteLine(i);}}},51,例子2.8的程序代碼說(shuō)明,本例代碼首先定義了一個(gè)靜態(tài)類(lèi)EMClass,在類(lèi)的內(nèi)部定義了一個(gè)靜態(tài)方法ToInt,注意該方法的定義參數(shù)有一個(gè)this關(guān)鍵字(擴(kuò)展方法可以有多個(gè)參數(shù),但是只有第一個(gè)參數(shù)能被this修飾,表示它代表要被擴(kuò)展的類(lèi)型,這里是String),該方法實(shí)現(xiàn)的邏輯是將字符串轉(zhuǎn)換為整數(shù);接下來(lái)在Main方法中生成一個(gè)字符串,在此實(shí)例對(duì)象上調(diào)用方法ToInt得到轉(zhuǎn)換后的數(shù)字結(jié)果“200”并在屏幕上打印顯示出來(lái)。,52,2.5泛型,目前主流的編程語(yǔ)言中,大部分是強(qiáng)類(lèi)型編程語(yǔ)言,即要求變量或?qū)ο蟊仨氂凶约旱念?lèi)型,不同類(lèi)型之間的轉(zhuǎn)換還要遵守嚴(yán)格規(guī)則。強(qiáng)類(lèi)型編程語(yǔ)言有助于編寫(xiě)更加安全的程序代碼,但是其通用性方面還有欠缺。考慮下面求2個(gè)整數(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á)式不用指定返回值,返回類(lèi)型可以從返回值或代理的返回值推定。,60,C#Lambda表達(dá)式來(lái)源,Lambda實(shí)際上源遠(yuǎn)流長(zhǎng),現(xiàn)在使用的機(jī)器都是馮-諾依曼體系的,屬于圖靈機(jī),在那之前還有一種稱(chēng)作λ演算的理論,但是圖靈機(jī)由于先被實(shí)現(xiàn)出來(lái),所以大行其道,λ演算后來(lái)成就了函數(shù)式編程語(yǔ)言特別是Lisp,在函數(shù)式編程語(yǔ)言里函數(shù)是第一等元素,函數(shù)的參數(shù),函數(shù)的返回值都是函數(shù),程序沒(méi)有變量,函數(shù)嵌套函數(shù)。而且函數(shù)式編程語(yǔ)言一直存在于象牙塔中,在工業(yè)界沒(méi)有流行。但近年來(lái)工業(yè)界比較喜歡“復(fù)古”風(fēng)格,而函數(shù)式編程語(yǔ)言能解決一些命令式編程難以解決的問(wèn)題(或者解決起來(lái)非常麻煩),所以也走上了歷史舞臺(tái)。C#要做到函數(shù)風(fēng)格編程怎么辦?靠原來(lái)的方法定義的方式肯定不行,2.0的匿名方法初步解決了這個(gè)問(wèn)題,但還不夠,3.0的Lambda終于很好的解決了,一個(gè)Lambda就是一個(gè)delegate,一個(gè)delegate指向一個(gè)方法,現(xiàn)在我們使用Lambda也能簡(jiǎn)單的將方法作為參數(shù)傳遞了,還可以層層嵌套,簡(jiǎn)化了編程。,61,Lambda表達(dá)式本質(zhì),lambda是一個(gè)匿名方法,其本質(zhì)上是匿名方法在語(yǔ)法上的簡(jiǎn)化,匿名方法具備的特性,lambda表達(dá)式也同樣具備。它可以包含表達(dá)式和語(yǔ)句,并且可用于創(chuàng)建委托或表達(dá)式樹(shù)類(lèi)型。使用lambda表達(dá)式是在C#2.0推出的匿名方法的特性基礎(chǔ)上,將匿名方法的語(yǔ)法進(jìn)一步簡(jiǎn)化。另外,lambda表達(dá)式還通過(guò)使用表達(dá)式樹(shù)推遲代碼的編譯時(shí)間,使得代碼可以在系統(tǒng)運(yùn)行時(shí)動(dòng)態(tài)編譯,增加代碼的靈活性。lambda表達(dá)式主要用于代替匿名方法,以更簡(jiǎn)潔的方式向方法中加入一些短小的代碼片段。,62,Lambda表達(dá)式對(duì)匿名方法的改進(jìn),先看一下匿名方法的使用。在.net2.0中System.Collections.-Generic命名空間下List里有一些新增的方法。比如Find,若使用匿名方法可寫(xiě)為:books.Find(delegate(Bookbook){returnbook.Pricebook.Pricex+1//后面跟著表達(dá)式Deleage(intx){returnx+1;}//后面跟著語(yǔ)句塊x=>{returnx+1;}//后面跟著語(yǔ)句塊Delegate(intx){returnx+1;}//輸入?yún)?shù)也可以帶類(lèi)型(intx)=>x+1//后面跟著表達(dá)式Delegate(intx){returnx+1;}//可輸入多個(gè)參數(shù),逗號(hào)分隔(x,y)=>x+y//后面跟著表達(dá)式Delegate(intx,inty){returnx+y;}//無(wú)參的也行()=>1//無(wú)參數(shù),后跟表達(dá)式Delegate(){return1;},64,Lambda表達(dá)式和語(yǔ)句,Lambda表達(dá)式的形式如下:(inputparameter)=>expressionlambda使用lambda運(yùn)算符=>,運(yùn)算符的左邊是可選的輸入?yún)?shù),右邊是表達(dá)式。該運(yùn)算符與賦值運(yùn)算符優(yōu)先級(jí)相同,也是右結(jié)合運(yùn)算符。Lambda語(yǔ)句的形式如下:(inputparameter)=>{statement;}Lambda的語(yǔ)句與表達(dá)式基本一樣,只是運(yùn)算符“=>”右面使用花括號(hào)包含的代碼快。,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語(yǔ)句外的變量“;MyDelegatedele2=(t,n)=>//定義lambda語(yǔ)句{Console.WriteLine(“從Lambda語(yǔ)句體中輸出”);Console.WriteLine(“輸出外部變量tmp:{0}”,tmp);strings;s=string.Format(”{0}{1}小姐“,t,n);returns;};Console.WriteLine(“調(diào)用Lambda語(yǔ)句\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á)式樹(shù),Lambda表達(dá)式樹(shù)是Lambda表達(dá)式以樹(shù)的形式表現(xiàn)出來(lái)的另外一種數(shù)據(jù)結(jié)構(gòu)。一個(gè)表達(dá)式樹(shù)是一個(gè)System.Linq.Expressions.Expression泛型的實(shí)例,委托類(lèi)型T是與此表達(dá)式樹(shù)相對(duì)應(yīng)的lambda表達(dá)式的委托類(lèi)型(System.Linq命名空間中對(duì)應(yīng)的Func類(lèi)型)。并不是所有的lambda表達(dá)式都可以被轉(zhuǎn)換為表達(dá)式樹(shù),只有那些只包含表達(dá)式主體內(nèi)容的lambda表達(dá)式(如(a,b)=>a+b)才可以被轉(zhuǎn)換。如果在主體中包含了聲明性質(zhì)的語(yǔ)句,則不能被轉(zhuǎn)換。,71,例子2.12lambda表達(dá)式樹(shù)的應(yīng)用,usingSystem;usingSystem.Linq.Expressions;namespaceDemoLambda{publicclassProgram{publicstaticvoidMain(string[]args){Expression>tree=n=>168;//定義表達(dá)式目錄樹(shù)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();//編譯目錄樹(shù)Console.WriteLine(“1000是否大于168:{0}“,t(1000));}}},72,例子2.12程序代碼和運(yùn)行結(jié)果,Lambda表達(dá)式樹(shù)負(fù)責(zé)分解、優(yōu)化Lambda表達(dá)式,實(shí)際應(yīng)用的機(jī)會(huì)不太多。結(jié)果如下:,73,2.7枚舉量和Yield,枚舉用于由有限多個(gè)選擇情況構(gòu)成的場(chǎng)合,枚舉類(lèi)型為一組符號(hào)常數(shù)提供了一個(gè)用戶自己定義的類(lèi)型名稱(chēng)。在枚舉中的每個(gè)成員實(shí)際上是一個(gè)符號(hào)常數(shù)。當(dāng)對(duì)有限多個(gè)選擇依次進(jìn)行循環(huán)操作時(shí),要求操作后返回到循環(huán)開(kāi)始處以便進(jìn)行下一次循環(huán)操作,而不是到return語(yǔ)句之后的語(yǔ)句繼續(xù)執(zhí)行,這就要使用到y(tǒng)ield關(guān)鍵字。,74,2.7.1枚舉類(lèi)型—enum,只要將需要的變量值一一列舉出來(lái),便構(gòu)成了一個(gè)枚舉類(lèi)型。枚舉類(lèi)型的聲明形式如下:enum枚舉類(lèi)型名{變量值列表};例如:enumweekday{sun,mon,tue,wed,thu,fri,sat};它聲明了一個(gè)枚舉類(lèi)型weekday,表示有sun,mon到sat的可能的七種情況,這七個(gè)單詞分別對(duì)應(yīng)了數(shù)字0,1,…,6。,75,枚舉類(lèi)型—enum,枚舉類(lèi)型應(yīng)用說(shuō)明:對(duì)枚舉元素按常量處理,不能對(duì)它們賦值。例如,不能寫(xiě):sun=0;枚舉元素具有默認(rèn)值,它們依次為:0,1,2,......。也可以在聲明時(shí)另行指定枚舉元素的值,如:enumweekday{sun=7,mon=1,tue,wed,thu,fri,sat};枚舉值可以進(jìn)行關(guān)系運(yùn)算。整數(shù)值不能直接賦給枚舉變量,如需要將整數(shù)賦值給枚舉變量,應(yīng)進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換。,76,枚舉成員的數(shù)值,一個(gè)枚舉成員的數(shù)值,既可以使用等號(hào)“=”顯示地賦值,也可以使用隱式賦值。對(duì)于隱式賦值按照以下的規(guī)則來(lái)確定值:——對(duì)第一個(gè)枚舉成員,如果沒(méi)有顯式賦值,則其被隱式賦予數(shù)值為0;——對(duì)于其它枚舉成員,如果沒(méi)有顯式賦值,它的數(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),編寫(xiě)程序順序輸出這四種情況。分析:由于比賽結(jié)果只有四種可能,所以可以聲明一個(gè)枚舉類(lèi)型,并聲明一個(gè)枚舉類(lèi)型的變量來(lái)存放比賽結(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時(shí),才產(chǎn)生枚舉,84,例子2.14枚舉類(lèi)的應(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)鍵字在迭代器中,用于向枚舉對(duì)象返回元素值或發(fā)出迭代結(jié)束信號(hào)。yield關(guān)鍵字的使用形式如下:yieldreturn;yieldbreak;yield關(guān)鍵字只能用在定義迭代器的代碼塊中,yieldreturn返回枚舉元素后,會(huì)保存迭代器的枚舉位置,當(dāng)下次調(diào)用迭代器時(shí),從保存的位置繼續(xù)執(zhí)行。,86,例子2.15使用yield關(guān)鍵字的迭代器,微軟從C#的高級(jí)版本2.0后,使用了簡(jiǎn)潔的迭代器foreach代替過(guò)去只適用于簡(jiǎn)單類(lèi)型的循環(huán)控制語(yǔ)句,如for和while。配合yield關(guān)鍵字,用極少量的代碼,就可以構(gòu)造一個(gè)迭代器,實(shí)現(xiàn)過(guò)去用for和while等語(yǔ)句很難實(shí)現(xiàn)的對(duì)各類(lèi)對(duì)象的循環(huán)控制。迭代器在C#中應(yīng)用廣泛,yield關(guān)鍵字在迭代器中向枚舉對(duì)象返回元素值或發(fā)出迭代結(jié)束信號(hào)。,87,例子2.15程序代碼(1),usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;namespaceDemoIterator1{///包含迭代器的自定義集合類(lèi)publicclassMyDocuments:IEnumerable{privateListdocs=newList();publicvoidAdd(strings){docs.Add(s);}#regionIEnumerable成員publicIEnumeratorGetEnumerator(){foreach(stringsindocs){yieldreturns;}}#endregion},88,例子2.15程序代碼(2),classProgram{staticvoidMain- 1.請(qǐng)仔細(xì)閱讀文檔,確保文檔完整性,對(duì)于不預(yù)覽、不比對(duì)內(nèi)容而直接下載帶來(lái)的問(wèn)題本站不予受理。
- 2.下載的文檔,不會(huì)出現(xiàn)我們的網(wǎng)址水印。
- 3、該文檔所得收入(下載+內(nèi)容+預(yù)覽)歸上傳者、原創(chuàng)作者;如果您是本文檔原作者,請(qǐng)點(diǎn)此認(rèn)領(lǐng)!既往收益都?xì)w您。
下載文檔到電腦,查找使用更方便
14.9 積分
下載 |
- 配套講稿:
如PPT文件的首頁(yè)顯示word圖標(biāo),表示該P(yáng)PT已包含配套word講稿。雙擊word圖標(biāo)可打開(kāi)word文檔。
- 特殊限制:
部分文檔作品中含有的國(guó)旗、國(guó)徽等圖片,僅作為作品整體效果示例展示,禁止商用。設(shè)計(jì)者僅對(duì)作品中獨(dú)創(chuàng)性部分享有著作權(quán)。
- 關(guān) 鍵 詞:
- 技術(shù)設(shè)計(jì) 應(yīng)用 NET 第二
鏈接地址:http://m.appdesigncorp.com/p-3219629.html