臺(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頁珍藏版)》請(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#語言相關(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,查詢表達(dá)式,4,C#的新特征,對(duì)于使用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í)際上就是原來變量即實(shí)參的別名,指向?qū)崊⒃趦?nèi)存中的位置,所以在方法中對(duì)引用類型參數(shù)的修改會(huì)導(dǎo)致對(duì)實(shí)參本身的改變。類似地,如果把方法也看成數(shù)據(jù),通過代理機(jī)制把方法賦值給一個(gè)變量,也就是把這個(gè)方法在內(nèi)存中的位置賦給變量,則通過這個(gè)變量就可以把這個(gè)方法傳遞給其他的方法調(diào)用。這種類型的變量就是代理類型的變量。,6,代理(委托)的實(shí)質(zhì),代理本身是一個(gè)類,它封裝了一個(gè)或多個(gè)方法。在內(nèi)部,一個(gè)代理保存方法指針(地址)的對(duì)照表,即這個(gè)代理類里面的每個(gè)方法名和它對(duì)應(yīng)的地址的列表。每個(gè)方法指針可以與一個(gè)引用實(shí)例配對(duì),而該實(shí)例是包含實(shí)例方法的類實(shí)例。聲明代理類型時(shí)在方法頭前面放上關(guān)鍵字delegate,例如:publicdelegatevoidPrintCallback(intno);,7,例子2.1代理的應(yīng)用實(shí)例分析,本例是文書自動(dòng)回信的局部功能演示。根據(jù)輸入的來信人姓名和性別,確定增加“先生”或“女士”的稱呼;根據(jù)處理來信時(shí)間,確定增加“你好”、“上午好”或“下午好”的問候語。這需要編制添加稱呼詞的兩個(gè)方法和添加時(shí)間問候詞的三個(gè)方法。為了在主程序中使代碼簡潔清晰,不用if語句分情況調(diào)用不同稱呼詞和問候語的辦法,而是采用兩個(gè)代理分別表示添加的內(nèi)容,問候語的區(qū)別通過代理的參數(shù)來解決。,8,例子2.1代理類型的應(yīng)用,usingSystem;NamespaceDemoDelegate1delegatevoidmyDelegate(strings);/無返回類型/的代理,添加問候詞delegatestringmyDelegateStr(strings,boolman);/有返回類型的代理,添加稱呼詞classProgramstaticvoidshow1(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(stringargs)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í)例分析,本例是對(duì)一個(gè)有10個(gè)元素的整形數(shù)組,分別調(diào)用三個(gè)不同的方法過濾選出其偶數(shù)、奇數(shù)和大于5的數(shù)的子集并顯示。為了實(shí)現(xiàn)這個(gè)目的,一般是分別編寫篩選偶數(shù)的方法IsEven、篩選奇數(shù)的方法IsOdd和篩選大于5的數(shù)的方法IsOver5,然后在程序里分別調(diào)用它們來實(shí)現(xiàn)要求。更簡潔的辦法是采用代理技術(shù),設(shè)計(jì)一個(gè)代理類型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ù)組全部元素過濾挑選的任務(wù),又設(shè)計(jì)了一個(gè)方法FilterArray,它接受待過濾的數(shù)組和代理類型NumPredicate的引用變量作為參數(shù),并按照每次引用變量所指向的方法對(duì)數(shù)組進(jìn)行具體的過濾操作。對(duì)每次選中的結(jié)果調(diào)用方法DisplayList全部顯示出來。本例中采用了列表結(jié)構(gòu)List作為存放選中數(shù)組元素結(jié)果的保存結(jié)構(gòu)。,15,例子2.2代理類型的應(yīng)用,usingSystem;usingSystem.Collection.Generic;classDelegatespublicdelegateboolNumPredicate(intnum);publicstaticvoidMain()intnumber=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(intintAr,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(number5);/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ì)象并在同一語句中將其屬性初始化。這適用于類沒有提供所需要的構(gòu)造函數(shù)的情況。采用初始化器時(shí),不能寫與類同名的構(gòu)造方法,而是寫一個(gè)與類同名的初始化器,即原來構(gòu)造方法名字后面的圓括號(hào)“()”被一組花括號(hào)“”和類里面變量成員的初始值所代替。,21,對(duì)象初始化器的特點(diǎn),例如,Time1類的默認(rèn)構(gòu)造方法:Time1time=newTime1();采用初始化器時(shí)就變成:Time1time=newTime1Hour=0,Minute=0,Second=0;采用初始化器時(shí),類里面就不能編寫任何構(gòu)造方法。,22,例子2.3Time類的對(duì)象初始化器,publicclassTimeprivateinthour;/023privateintminute;/059privateintsecond;/059publicvoidSetTime(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:D23”,(hour=0|hour=12)?12:hour%12),hour,minute,second,(hour=0,25,例子2.3程序代碼(續(xù)3),usingSystem;publicclassObjectInitializerTestpublicstaticvoidMain(stringargs)Console.Write(“Timeobjectcreatedwithobjectinitializer“);Timetime=newTimeHour=14,Minute=145,Second=12;Console.Write(“Standardtime0:“,time.ToString();Console.Write(“Universaltime0:“,time.ToUniversalString();Console.Write(“TimeobjectcreatedwithMinutepropertyset“);Timeanothertime=newTimeMinute=45;Console.Write(“Standardtime0:“,anothertime.ToString();Console.Write(“Universaltime0:“,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ì)象初始化器中指定的值無效(如Minute=0145),則set方法強(qiáng)制設(shè)其為0。,27,集合初始化器,如果集合實(shí)現(xiàn)了泛型System.Collections.Generic-.ICollections接口,并且指定了T的類型,就可以使用集合初始化器來對(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;namespaceDemoInitislizerclassGirlfriend/DemoObjectpublicstringNameget;set;publicintAgeget;set;classBoyfriend/DemoObjectpublicstringNameget;set;publicintAgeget;set;publicListGirlsget;set;/SetAttribute,29,例子2.4程序代碼(續(xù)),publicclassSetInitializerTestpublicstaticvoidMain(stringargs)Listgfs1=newList“Mary”,“Susan”,”Lucy”;Listgfs2=newList();gfs2.Add(“Mary”);gfs2.Add(“Susan”);gfs2.Add(”Lucy”);Boyboy=newBoyName=“Tom”,Age=24,Girls=newListnewGirlfriendName=“Mary”,Age=23,newGirlfriendName=“Susan”,Age=19,newGirlfriendName=“Lucy”,Age=21;,30,例子2.4程序代碼的分析說明,本例中,對(duì)于gfs1就是用集合初始化器創(chuàng)建的它等價(jià)于gfs2對(duì)每一個(gè)元素分別調(diào)用元素初始化器ICollection.Add(T)方法。對(duì)Boy類的對(duì)象boy使用了對(duì)象初始化器與集合初始化器的復(fù)合使用,用一條語句完成了對(duì)多個(gè)對(duì)象和整個(gè)集合的初始化。,31,2.3匿名類型,匿名類型顧名思義就是沒有類的名稱,也就是沒有類的定義,但是它有類體,可以創(chuàng)建簡單類,用于存儲(chǔ)數(shù)據(jù)。匿名類型聲明也稱為匿名對(duì)象生成表達(dá)式,類似于初始化器,其聲明的開頭是關(guān)鍵字new,然后是成員初始化器列表,放在花括號(hào)中。在new后面是不能有類的構(gòu)造方法名(與類名相同)的。例如:varbob=newName=“BobSmith”,Age=26;聲明了一個(gè)匿名類對(duì)象bob,且其屬性Name=“BobSmith”,Age=26。注意這個(gè)類沒有類名。,32,例子2.5使用匿名類的例子,usingSystem;classAnonymousTypesstaticvoidMain()varbob=newName=“BobSmith”,Age=37;Console.WriteLine(“Bob:”,bob.ToString();varsteve=newName=“SteveJones”,Age=26;Console.WriteLine(“Steve:”,steve.ToString();Console.WriteLine(“nBobandSteveare0:”,(bob.Equals(steve)?“equal”:“notequal”);,33,例子2.5使用匿名類的例子(續(xù)),varbob2=newName=“BobSmith”,Age=37;Console.WriteLine(“nBob2:”,bob2.ToString();Console.WriteLine(“nBobandBob2are0:”,(bob.Equals(steve)?“equal”:“notequal”);/endMainmethod,34,Bob:Name=BobSmith,Age=37Steve:Name=SteveJones,Age=26BobandStevearenotequalBob2:Name=BobSmith,Age=37BobandBob2areequal分析:上例中使用了隱式類型局部變量保存對(duì)匿名類型對(duì)象的引用,如varbob=newName=“BobSmith”,Age=37;還用匿名類型的方法ToString()在控制臺(tái)上顯示這個(gè)對(duì)象的信息。編譯器在創(chuàng)建匿名類型定義時(shí)定義ToString方法,它返回的字符串放在花括號(hào)中。例子中還創(chuàng)建了另一個(gè)匿名類對(duì)象Steve,其使用的初始化器內(nèi)容與bob的相同,被認(rèn)為相同類型。比較兩個(gè)匿名類對(duì)象相等,要檢查他們的所有屬性(這里是Name和Age),有其中一個(gè)不等,則兩個(gè)匿名類對(duì)象不相等。,34,例子2.5運(yùn)行結(jié)果,35,匿名類型的進(jìn)一步說明,匿名類型一般出現(xiàn)在ADO.NET的select子句中,用來投影篩選出的數(shù)據(jù)。匿名類型使用new運(yùn)算符和對(duì)象初始值設(shè)定項(xiàng)來創(chuàng)建。匿名類型創(chuàng)建的屬性是只讀的,匿名類型的名稱和屬性的數(shù)據(jù)類型由編譯器隨機(jī)指定或自動(dòng)推斷。,36,匿名類型的進(jìn)一步說明,匿名類型不允許包含屬性以外的成員,不能強(qiáng)制轉(zhuǎn)換為Object以外的類型或接口,如果匿名類型賦值給變量,必須使用var關(guān)鍵字構(gòu)建此變量。多個(gè)匿名類型具有相同的順序、相同數(shù)量和種類的屬性成員,編譯器會(huì)將這些匿名類型視為相同的類型,并且它們共享編譯器生成的類型信息。,37,例子2.6匿名類型創(chuàng)建類,usingSystem;usingSystem.Linq;usingSystem.Collections.Generic;namespaceDemoAnonymousTypeclassProgrampublicstaticvoidMain(stringargs)varanonymous1=/創(chuàng)建匿名類型newName=“安碧茹”,Title=“苗族圣姑”,Age=36;varanonymous2=/創(chuàng)建匿名類型,類型同上newName=“寧雨昔”,Title=“圣坊仙子”,Age=37;Listlst=newList“高麗公主”,“大華軍師”,“霓裳公主”;Console.WriteLine(“anonymous1的類型:0”,anonymous1.GetType().Name);Console.WriteLine(“012”,anonymous1.Name,anonymous1.Title,anonymous1.Age);,38,例子2.6匿名類型創(chuàng)建類(續(xù)),Console.WriteLine(“anonymous2的類型:0”,anonymous2.GetType().Name);Console.WriteLine(“012”,anonymous2.Name,anonymous2.Title,anonymous2.Age);Console.WriteLine(“*”);varquery=fromninlst/LINQselect子句中創(chuàng)建匿名類型wheren.IndexOf(“公主”)-1selectnewName=“查詢?cè)亍?Title=n;/LINQ的select子句把查詢到的元素投影成匿名類型foreach(variteminquery)Console.WriteLine(“元素的類型:0”,item.GetType().Name);Console.WriteLine(“01”,item.Name,item.Title);,39,例子2.6匿名類型創(chuàng)建類的分析,本例用var定義的兩個(gè)匿名類型對(duì)象anonymous1、anonymous2由于屬性的類型、順序相同,所以這兩個(gè)匿名類型生成的類型也是一致的。本例在LINQ查詢中的的select子句也創(chuàng)建了一個(gè)匿名類型,其類型也與上面定義的兩個(gè)匿名對(duì)象的類型是一致的:selectnewName=“查詢?cè)亍?Title=n;,40,例子2.6匿名類型創(chuàng)建類的運(yùn)行結(jié)果,anonymous1的類型:f_AnonymousType03安碧茹苗族圣姑36anonymous2的類型:_AnonymousType03寧雨昔圣坊仙子37*元素的類型:f_AnonymousType12查詢?cè)馗啕惞髟氐念愋停篺_AnonymousType12查詢?cè)啬奚压?41,2.4擴(kuò)展方法:對(duì)現(xiàn)有類增加新方法,有時(shí)需要在現(xiàn)有類里面增加新的功能或方法,但是由于受到一些限制又無法對(duì)這些類進(jìn)行修改。就可以利用類的擴(kuò)展方法在不必修改類的代碼的前提下為現(xiàn)有類增加新的功能。例如,Time類沒有顯示時(shí)間的方法,增加一個(gè)擴(kuò)展方法DisplayTime,它用Time對(duì)象的ToString方法在控制臺(tái)窗口中顯示時(shí)間。,42,擴(kuò)展方法的特點(diǎn)(續(xù)),新增的DisplayTime方法不必修改Time類的源代碼,關(guān)鍵是在其方法頭的參數(shù)表中的Time對(duì)象參數(shù)前面添加關(guān)鍵字this。關(guān)鍵字this告訴編譯器DisplayTime方法擴(kuò)展了現(xiàn)有類。C#編譯器將用這個(gè)信息把增加的代碼插入編譯的程序中,使得現(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ò)展方法的第一個(gè)參數(shù)的數(shù)據(jù)類型,決定這個(gè)方法應(yīng)用于哪個(gè)類型,在其前面還需標(biāo)有this關(guān)鍵字。,44,例子2.7Time類的擴(kuò)展方法,usingSystem;classTimeExtensionsTeststaticvoidMain(stringargs)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ù)),staticclassTimeExtensionspublicstaticvoidDisplayTime(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)用,本例編寫一個(gè)把字符串類型變量s通過調(diào)用一個(gè)轉(zhuǎn)換方法ToInt,轉(zhuǎn)換成數(shù)字的程序。由于在字符串類型中沒有這個(gè)方法,而字符串類型已經(jīng)是系統(tǒng)直接定義好的,故采取擴(kuò)展方法技術(shù)增加這個(gè)方法,使用起來就像ToInt方法是String類型的一個(gè)實(shí)例方法一樣。例如:Strings=“200”;inti=s.ToInt();,49,例子2.8擴(kuò)展方法的應(yīng)用(續(xù)),但是,實(shí)例方法只能通過一個(gè)類的實(shí)例(對(duì)象)來調(diào)用,不能直接通過類名來調(diào)用。而靜態(tài)方法則只能通過類名來調(diào)用。例如,String類型的ToUpper方法就是一個(gè)實(shí)例方法,只能在一個(gè)String類型的對(duì)象上被調(diào)用,如:stringname=“Joe”;Console.WriteLine(name.ToUpper();,50,例子2.8擴(kuò)展方法的應(yīng)用實(shí)例,usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespaceDemoExtensionMethodspublicstaticclassEMClasspublicststicintToInt(thisstrings)returnInt32.Parse(s);classProgramstaticvoidMain(stringargs)strings=“200”;inti=s.ToInt();/調(diào)用擴(kuò)展方法,無需傳遞參數(shù)Console.WriteLine(i);,51,例子2.8的程序代碼說明,本例代碼首先定義了一個(gè)靜態(tài)類EMClass,在類的內(nèi)部定義了一個(gè)靜態(tài)方法ToInt,注意該方法的定義參數(shù)有一個(gè)this關(guān)鍵字(擴(kuò)展方法可以有多個(gè)參數(shù),但是只有第一個(gè)參數(shù)能被this修飾,表示它代表要被擴(kuò)展的類型,這里是String),該方法實(shí)現(xiàn)的邏輯是將字符串轉(zhuǎn)換為整數(shù);接下來在Main方法中生成一個(gè)字符串,在此實(shí)例對(duì)象上調(diào)用方法ToInt得到轉(zhuǎn)換后的數(shù)字結(jié)果“200”并在屏幕上打印顯示出來。,52,2.5泛型,目前主流的編程語言中,大部分是強(qiáng)類型編程語言,即要求變量或?qū)ο蟊仨氂凶约旱念愋停煌愋椭g的轉(zhuǎn)換還要遵守嚴(yán)格規(guī)則。強(qiáng)類型編程語言有助于編寫更加安全的程序代碼,但是其通用性方面還有欠缺。考慮下面求2個(gè)整數(shù)中的較小者:intMin(inta,intb)if(ab)returna;elsereturnb;根據(jù)上面的代碼,對(duì)于每一種希望比較的參數(shù)類型,比如long、float、double等,就需要編寫一個(gè)該類型版本的函數(shù)。這就增大了程序員的工作量,非常不方便,也容易出錯(cuò)。,53,泛型概述,泛型是用于處理算法、數(shù)據(jù)結(jié)構(gòu)的一種編程方法。其目標(biāo)是采用廣泛適用和可交互性的形式來表示算法和數(shù)據(jù)結(jié)構(gòu),以使它們能夠直接用于軟件構(gòu)造。泛型類、結(jié)構(gòu)、接口、委托和方法可以根據(jù)它們存儲(chǔ)和操作的數(shù)據(jù)的類型來進(jìn)行參數(shù)化。泛型能在編譯時(shí)提供強(qiáng)大的類型檢查,減少數(shù)據(jù)類型之間的顯示轉(zhuǎn)換。泛型類和泛型方法同時(shí)具備可重用性、類型安全和效率高等特性,通常用在集合和在集合上運(yùn)行的方法中。,54,問題的產(chǎn)生,我們編寫一個(gè)具有通用性質(zhì)的Min方法如下:ObjectMin(Objecta,Objectb)if(ab)returna;elsereturnb;期望用對(duì)象Object代替具體的數(shù)據(jù)類型當(dāng)作占位符,對(duì)任何類型的兩個(gè)對(duì)象Object都能找出比較小的數(shù)。但是由于比較操作符“”不是定義在Object類型上的操作符,因而該段代碼無法執(zhí)行??梢越柚粋€(gè)通用的IComparable接口來實(shí)現(xiàn)比較運(yùn)算。故上述代碼修改如下:IComparableMin(IComparablea,IComparableb)if(a.CompareTo(b)0)returna;elsereturnb;,55,泛型的引入,適應(yīng)通用類型對(duì)象的問題解決后,又產(chǎn)生了新的問題。即每次使用這段代碼時(shí),都必須進(jìn)行類型轉(zhuǎn)換。如下面的方法調(diào)用代碼需要將方法的返回值轉(zhuǎn)換為整數(shù)類型:inta=3,b=5;intc=(int)Min(a,b);頻繁的類型轉(zhuǎn)換會(huì)消耗計(jì)算機(jī)資源,造成程序的執(zhí)行效率下降。為了從根本上解決問題,C#從2.0版就提出了泛型(generics)的概念,用泛型改編上面的代碼為:TMin(Ta,Tb)whereT:IComparable/CompareTo方法是接口IComparable的方法if(a.CompareTo(b)(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ù)式編程語言能解決一些命令式編程難以解決的問題(或者解決起來非常麻煩),所以也走上了歷史舞臺(tái)。C#要做到函數(shù)風(fēng)格編程怎么辦?靠原來的方法定義的方式肯定不行,2.0的匿名方法初步解決了這個(gè)問題,但還不夠,3.0的Lambda終于很好的解決了,一個(gè)Lambda就是一個(gè)delegate,一個(gè)delegate指向一個(gè)方法,現(xiàn)在我們使用Lambda也能簡單的將方法作為參數(shù)傳遞了,還可以層層嵌套,簡化了編程。,61,Lambda表達(dá)式本質(zhì),lambda是一個(gè)匿名方法,其本質(zhì)上是匿名方法在語法上的簡化,匿名方法具備的特性,lambda表達(dá)式也同樣具備。它可以包含表達(dá)式和語句,并且可用于創(chuàng)建委托或表達(dá)式樹類型。使用lambda表達(dá)式是在C#2.0推出的匿名方法的特性基礎(chǔ)上,將匿名方法的語法進(jìn)一步簡化。另外,lambda表達(dá)式還通過使用表達(dá)式樹推遲代碼的編譯時(shí)間,使得代碼可以在系統(tǒng)運(yùn)行時(shí)動(dòng)態(tài)編譯,增加代碼的靈活性。lambda表達(dá)式主要用于代替匿名方法,以更簡潔的方式向方法中加入一些短小的代碼片段。,62,Lambda表達(dá)式對(duì)匿名方法的改進(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;/可輸入多個(gè)參數(shù),逗號(hào)分隔(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)先級(jí)相同,也是右結(jié)合運(yùn)算符。Lambda語句的形式如下:(inputparameter)=statement;Lambda的語句與表達(dá)式基本一樣,只是運(yùn)算符“=”右面使用花括號(hào)包含的代碼快。,65,例子2.10創(chuàng)建lambda表達(dá)式,usingSystem;namespaceDemolambdaclassProgramdelegatestringMyDelegate(stringt,stringn);staticvoidMain(stringargs)MyDelegatedele=(t,n)=/定義lambda表達(dá)式string.Format(“01”,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(”01小姐“,t,n);returns;Console.WriteLine(“調(diào)用Lambda語句n”);Console.WriteLine(dele2(“Ms”,“Kathy”);,67,例子2.11lambda表達(dá)式的應(yīng)用,usingSystem;usingSystem.Collection.Generic;classLambdapublicdelegateboolNumPredicate(intnum);publicstaticvoidMain()intnumber=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=returnnum5;);DisplayList(”Usealambda-expressiontofilternumbersover5:”,NumberOver5);/endMainmethod,68,例子2.11程序代碼(續(xù)),privatestaticListFilterArray(intintAr,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)。一個(gè)表達(dá)式樹是一個(gè)System.Linq.Expressions.Expression泛型的實(shí)例,委托類型T是與此表達(dá)式樹相對(duì)應(yīng)的lambda表達(dá)式的委托類型(System.Linq命名空間中對(duì)應(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;namespaceDemoLambdapublicclassProgrampublicstaticvoidMain(stringargs)Expressiontree=n=168;/定義表達(dá)式目錄樹BinaryExpressionbody=(BinaryExpression)tree.168;ParameterExpressionleft=(ParameterExpression)body.Left;ConstantExpressionright=(ConstantExpression)body.Right;Console.WriteLine(“分解結(jié)果:012n”,/分解結(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ī)會(huì)不太多。結(jié)果如下:,73,2.7枚舉量和Yield,枚舉用于由有限多個(gè)選擇情況構(gòu)成的場合,枚舉類型為一組符號(hào)常數(shù)提供了一個(gè)用戶自己定義的類型名稱。在枚舉中的每個(gè)成員實(shí)際上是一個(gè)符號(hào)常數(shù)。當(dāng)對(duì)有限多個(gè)選擇依次進(jìn)行循環(huán)操作時(shí),要求操作后返回到循環(huán)開始處以便進(jìn)行下一次循環(huán)操作,而不是到return語句之后的語句繼續(xù)執(zhí)行,這就要使用到y(tǒng)ield關(guān)鍵字。,74,2.7.1枚舉類型enum,只要將需要的變量值一一列舉出來,便構(gòu)成了一個(gè)枚舉類型。枚舉類型的聲明形式如下:enum枚舉類型名變量值列表;例如:enumweekdaysun,mon,tue,wed,thu,fri,sat;它聲明了一個(gè)枚舉類型weekday,表示有sun,mon到sat的可能的七種情況,這七個(gè)單詞分別對(duì)應(yīng)了數(shù)字0,1,6。,75,枚舉類型enum,枚舉類型應(yīng)用說明:對(duì)枚舉元素按常量處理,不能對(duì)它們賦值。例如,不能寫:sun=0;枚舉元素具有默認(rèn)值,它們依次為:0,1,2,.。也可以在聲明時(shí)另行指定枚舉元素的值,如:enumweekdaysun=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ù)值,一個(gè)枚舉成員的數(shù)值,既可以使用等號(hào)“=”顯示地賦值,也可以使用隱式賦值。對(duì)于隱式賦值按照以下的規(guī)則來確定值:對(duì)第一個(gè)枚舉成員,如果沒有顯式賦值,則其被隱式賦予數(shù)值為0;對(duì)于其它枚舉成員,如果沒有顯式賦值,它的數(shù)值被隱式地賦為前一枚舉成員的值加1;例如enumColorred,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é)果只有四種可能,所以可以聲明一個(gè)枚舉類型,并聲明一個(gè)枚舉類型的變量來存放比賽結(jié)果。,78,usingSystem;publicclassEnumTestpublicstaticvoidMain()enumgame_resultWIN,LOSE,TIE,CANCEL;game_resultresult;enumgame_resultomit=CANCEL;for(intcount=WIN;count0)_counter-;returntrue;elsereturnfalse;publicvoidReset()_counter=_countdown.StartCountdown;publicobjectCurrentgetreturn_counter;/當(dāng)代碼段使用CountdownEnumerator時(shí),才產(chǎn)生枚舉,84,例子2.14枚舉類的應(yīng)用(續(xù)2),publicclassDemoEnumeratorpublicstaticvoidDemoCountdown()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(“0BIS”,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后,使用了簡潔的迭代器foreach代替過去只適用于簡單類型的循環(huán)控制語句,如for和while。配合yield關(guān)鍵字,用極少量的代碼,就可以構(gòu)造一個(gè)迭代器,實(shí)現(xiàn)過去用for和while等語句很難實(shí)現(xiàn)的對(duì)各類對(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/包含迭代器的自定義集合類publicclassMyDocuments:IEnumerableprivateListdocs=newList();publicvoidAdd(strings)docs.Add(s);#regionIEnumerable成員publicIEnumeratorGetEnumerator()foreach(stringsindocs)yieldreturns;#endregion,88,例子2.15程序代碼(2),classProgramstaticvoidMain- 1.請(qǐng)仔細(xì)閱讀文檔,確保文檔完整性,對(duì)于不預(yù)覽、不比對(duì)內(nèi)容而直接下載帶來的問題本站不予受理。
- 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文件的首頁顯示word圖標(biāo),表示該P(yáng)PT已包含配套word講稿。雙擊word圖標(biāo)可打開word文檔。
- 特殊限制:
部分文檔作品中含有的國旗、國徽等圖片,僅作為作品整體效果示例展示,禁止商用。設(shè)計(jì)者僅對(duì)作品中獨(dú)創(chuàng)性部分享有著作權(quán)。
- 關(guān) 鍵 詞:
- 技術(shù)設(shè)計(jì) 應(yīng)用 NET 第二
鏈接地址:http://ioszen.com/p-3219629.html