版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
在類的構(gòu)造函數(shù)中出現(xiàn)表示對(duì)正在構(gòu)造的對(duì)象本身的引用,在類的方法中出現(xiàn)表示對(duì)調(diào)用該方法的對(duì)象的引用,在結(jié)構(gòu)的構(gòu)造上函數(shù)中出現(xiàn)表示對(duì)正在構(gòu)造的結(jié)構(gòu)的引用,在結(jié)構(gòu)的方法中出現(xiàn)表示對(duì)調(diào)用該方法的結(jié)果的引用在C#系統(tǒng)中,this實(shí)際上是ー個(gè)常量,所以不能使用this++這樣的運(yùn)算this保留字一般用于限定同名的隱蔵成員、將對(duì)象本身做為參數(shù)、聲明索引訪問(wèn)器、判斷傳入?yún)?shù)的對(duì)象是否為本身?類和結(jié)構(gòu)的區(qū)別?答:類:類是引用類型在堆上分配,類的實(shí)例進(jìn)行賦值只是復(fù)制了引用,都指向同一段實(shí)際對(duì)象分配的內(nèi)存;類有構(gòu)造和析構(gòu)函數(shù);類可以繼承和被繼承。結(jié)構(gòu):結(jié)構(gòu)是值類型在棧上領(lǐng)(雖然棧的訪問(wèn)速度比較堆要快,但棧的資源有限放),結(jié)構(gòu)的賦值將分配產(chǎn)生一個(gè)新的對(duì)象。結(jié)構(gòu)沒有構(gòu)造函數(shù),但可以添加。結(jié)構(gòu)沒有析構(gòu)函數(shù)。結(jié)構(gòu)不可以繼承自另一個(gè)結(jié)構(gòu)或被繼承,但和類ー樣可以繼承自接口。.抽象類和接口的區(qū)別?答:抽象類(abstractclass)可以包含功能定義和實(shí)現(xiàn),接口(interface)只能包含功能定義抽象類是從ー系列相關(guān)對(duì)象中抽象出來(lái)的概念,因此反映的是事物的內(nèi)部共性;接口是為了滿足外部調(diào)用而定義的ー個(gè)功能約定,因此反映的是事物的外部特性分析對(duì)象,提煉內(nèi)部共性形成抽象類,用以表示對(duì)象本質(zhì),即“是什么”為外部提供調(diào)用或功能需要擴(kuò)充時(shí)優(yōu)先使用接口。接ロ一般只有方法,而沒有數(shù)據(jù)成員或?qū)傩浴3橄箢愑蟹椒?也有數(shù)據(jù)成員或?qū)傩?一般情況下,優(yōu)先考慮用接口,只有當(dāng)可能要訪問(wèn)到數(shù)據(jù)成員或?qū)傩詴r(shí),用抽象類。.概述深度復(fù)制和淺度復(fù)制深度復(fù)制就是將引用成員指向的對(duì)象也進(jìn)行復(fù)制。實(shí)際的過(guò)程是創(chuàng)建新的引用成員指向的對(duì)象,然后復(fù)制對(duì)象包含的數(shù)據(jù)。淺度復(fù)制的時(shí)候,對(duì)于值類型成員,會(huì)復(fù)制其本身(值類型變量本身包含了所有數(shù)據(jù),復(fù)制時(shí)進(jìn)行按位拷貝);對(duì)于引用類型成員(注意它會(huì)引用另ー個(gè)對(duì)象),僅僅復(fù)制引用,而不創(chuàng)建其引用的對(duì)象。結(jié)果就是:新對(duì)象的引用成員和復(fù)制對(duì)象的引用成員指向了同一個(gè)對(duì)象第十章定義類成員本章內(nèi)容.定義類成員.類成員的其他議題.接ロ的實(shí)現(xiàn).部分類知識(shí)點(diǎn).定義字段字段(一般首字母小寫,或下戈I踐開頭):在類中直接定義的變量。變量一定要先聲明,再賦值,才能使用.>命名規(guī)則:1)必須以“字母”ー或@符號(hào)開頭.ー不要以數(shù)字開頭2)后面可以跟任意“字母”、數(shù)字、下劃線.定義變量時(shí),變量名要有意義A注意:1)你起的變量名不要與c#系統(tǒng)中的關(guān)鍵字重復(fù).2)在c#中,大小寫是敏感的>字段用標(biāo)準(zhǔn)的變量聲明格式和前面介紹的修飾符來(lái)聲明(也可以初始化),例如:classmyClass(publicintMylnt;)公共字段推薦用PascalCasing的形式來(lái)命名,私有字段沒有推薦的命名形式,一般使用cameICasing的形式來(lái)命名。字段可以使用關(guān)鍵字readonly,表示這個(gè)字段只能在執(zhí)行構(gòu)造函數(shù)的過(guò)程中賦值,或由初始化語(yǔ)句賦值,例如:classmyClasspublicreadonlyintMylnt=17;)字段也可以使用static聲明為靜態(tài)的:classmyClass(publicstaticintMylnt;).定義屬性屬性(一般首字母大寫):定義一個(gè)public變量,這個(gè)變量里含有g(shù)et,set兩個(gè)方法(屬性不是變量,其實(shí)質(zhì)是函數(shù))0get讀取屬性,return返回讀取值,set寫屬性,關(guān)鍵字value存儲(chǔ)用戶賦的值。字段與屬性的區(qū)別就是可以進(jìn)行非法值的判斷。允許外部訪問(wèn)的變量一定要聲明為屬性。它是代表類的實(shí)例或類中的ー個(gè)數(shù)據(jù)項(xiàng)的成員。像字段:它是命名的類成員、有類型、可以被賦值和讀取;不像字段:它是函數(shù)成員、不為數(shù)據(jù)存儲(chǔ)分配內(nèi)存、它執(zhí)行代碼。屬性可以使用vartual、override和abstract關(guān)鍵字,但是不能將這幾個(gè)關(guān)鍵字用于字段。>語(yǔ)法:[訪問(wèn)修飾符]類型名屬性名{get{return字段;set(私有字段=valueJ))功能:允許外部訪問(wèn)的變量必須設(shè)為屬性,可以防止用戶設(shè)非法值,用來(lái)保護(hù)私有字段賦值的正確性。get塊一般有一個(gè)屬性類型的返回值,簡(jiǎn)單的屬性一般與一個(gè)私有字段相關(guān)聯(lián),用來(lái)控制對(duì)這個(gè)字段的訪問(wèn),這是get塊可以直接返回該字段的值;上面的字段外部不能訪問(wèn),只能通過(guò)屬性來(lái)訪問(wèn)該字段。set函數(shù)以類似的方式把ー個(gè)值賦給字段,這里可以使用關(guān)鍵字value引用用戶提供的屬性值;value值等于類型和屬性相同的一個(gè)值,如果屬性的類型和字段的類型相同,就不用進(jìn)行類型轉(zhuǎn)換。>靜態(tài)屬性:不能訪問(wèn)類的實(shí)例成員,雖然它們能被實(shí)例成員訪問(wèn);它總是存在,不管類是否有實(shí)例;當(dāng)從類的外部訪問(wèn)時(shí),必須使用類名引用,而不是實(shí)例名;>其設(shè)計(jì)目的主要是為了實(shí)現(xiàn)面向?qū)ο螅ī柀枺┲械姆庋b思想。根據(jù)該思想,字段最好設(shè)為private,一個(gè)精巧的類最好不要直接把字段設(shè)為公有提供給客戶調(diào)用端直接訪問(wèn)。.定義方法方法使用標(biāo)準(zhǔn)的函數(shù)格式,以及可訪問(wèn)性,和可選的static修飾符來(lái)聲明,例如:classmyClasspublicstringMyStringOreturn"這是一個(gè)方法”;)}解析:classmyClass(〃開始聲明方法代碼publicstringMyStringO(return"這是一個(gè)方法”;)〃結(jié)束聲明方法代碼)公共方法也用PascalCasing的形式來(lái)命名。>注意:如果聲明了static關(guān)鍵字,這個(gè)方法就只能通過(guò)類來(lái)訪問(wèn),而不能通過(guò)對(duì)象實(shí)例還訪問(wèn)。>也可以在方法定義中使用下面的關(guān)鍵字:virtual 方法可以重寫;abstract 方法必須在非抽象的派生類中重寫(只用于抽象類)override一一一方法重寫了一個(gè)基類方法(要重寫方法,必須用這個(gè)關(guān)鍵字)extern 方法定義在其他地方;構(gòu)造方法是ー種創(chuàng)建對(duì)象的特殊方法,方法名和類名ー樣,沒有返回值,連void都不用,就是為了初始化類的成員。構(gòu)造方法不能被。verride。構(gòu)造函數(shù)可以有參數(shù),new對(duì)象的時(shí)候傳遞函數(shù)參數(shù)即可。如果不指定構(gòu)造函數(shù),則類有一個(gè)默認(rèn)的無(wú)參構(gòu)造函數(shù)。如果指定了構(gòu)造函數(shù),則不再有默認(rèn)的無(wú)參構(gòu)造函數(shù),如果需要無(wú)參構(gòu)造函數(shù),則需要自己來(lái)寫。構(gòu)造函數(shù)可以臓,也就是有多個(gè)參數(shù)不同的構(gòu)造函數(shù)。使用構(gòu)造方法的好處:1.對(duì)多個(gè)屬性進(jìn)行賦值時(shí),不需要重復(fù)的寫實(shí)例名。2.可以保證用戶在newー個(gè)對(duì)象的時(shí)候必須對(duì)某ー個(gè)屬性進(jìn)行賦值。3.在newー個(gè)對(duì)象時(shí),對(duì)只讀屬性進(jìn)行初始化。在方法定義中,被virtual修飾的方法稱為虛函數(shù)。是沒有實(shí)現(xiàn)的,可由子類繼承并重寫的函數(shù)。在方法定義中,被修飾的方法稱為虛函數(shù)抽象函數(shù):規(guī)定其非虛子類必須實(shí)現(xiàn)的函數(shù),必須被重寫>定義方法一般有以下幾種://有返回值方法//調(diào)用例子://inti=2;//intresult=Add(i);//Console.WriteLine(result);//Console.WriteLine(i);//輸出后結(jié)果為3和2〃參數(shù)為值類型,原值不被修改publicstaticintAdd(intToNumber)(intsum=0;for(inti=1;i<=ToNumber;i++)(sum+=i;Ireturnsum;}〃無(wú)返回值方法〃調(diào)用例子://AddVoid(2);//輸出后結(jié)果為3publicstaticvoidAddVoid(intToNumber)(intsum=0;for(inti=1;i<=ToNumber;i++)(sum+=i;)Console.WriteLine(sum);I〃引用類型方法〃調(diào)用例子//Testobj=newTest()://AddObject(obj);//Console.WriteLine(obj.Number);〃輸出結(jié)果為3〃傳入obj對(duì)象的的Number屬性,原屬性值是1,傳入后,對(duì)象的屬性也被修改〃引用類型參數(shù)是傳地址,不是傳值,所有引用類型的原值也會(huì)被修改publicstaticvoidAddObject(Testobj){obj.Number+=2;}〃數(shù)組參數(shù)方法//調(diào)用例子//int[]Number={1,2};//intresult=AddArray(Number);//Console.WriteLine(result);〃輸出結(jié)果為3publicstaticintAddArray(int[]ToNumber){intnum=0;foreach(variinToNumber){num+=i;}returnnum;)〃數(shù)組參數(shù)簡(jiǎn)化簡(jiǎn)化調(diào)用//調(diào)用例子//intResult=AddArrayV2(l,2,3);//Console.WriteLine(Result);〃輸出結(jié)果為6〃這種寫法簡(jiǎn)化數(shù)組參數(shù),調(diào)用時(shí)不需要定義數(shù)組,會(huì)自動(dòng)將參數(shù)轉(zhuǎn)換為數(shù)組值處理publicstaticintAddArrayV2(paramsint[]ToNumber){intnum=0;foreach(variinToNumber){num+=i;}returnnum;)〃傳地址參數(shù),參數(shù)必須初始值//調(diào)用例子//intNumber=2;//AddRef(refNumber);//Console.WriteLine(Number);//輸出結(jié)果為4〃普通的寫法值類型是直接傳值,引用類型傳地址〃雖然Number是值類型,但是用ref就變成傳地址了,所以原值也會(huì)被修改〃注意的是,調(diào)用的時(shí)候也要加ref,而且參數(shù)傳入前必須有初始值publicstaticvoidAddRef(refintToNumber)ToNumber+=2;〃傳地址參數(shù),參數(shù)無(wú)初始值//調(diào)用方法//intNumber;//AddOut(outNumber);//Console.WriteLine(Number);〃輸出結(jié)果為3〃此方法和ref一樣,也是將值類型參數(shù)傳入地址,原值也會(huì)被修改〃與ref不同的是,參數(shù)有方法體提供初始值publicstaticvoidAddOut(outintToNumber){ToNumber=1;ToNumber+=2;}?靜態(tài)方法和實(shí)例方法(定義和調(diào)用)靜態(tài)實(shí)例(非靜態(tài))static關(guān)鍵字不需要static關(guān)鍵字使用類名調(diào)用使用實(shí)例對(duì)象調(diào)用在靜態(tài)方法中,可以訪問(wèn)靜態(tài)成員在實(shí)例方法中:可以直接訪問(wèn)靜態(tài)成員在靜態(tài)方法中,不可以直接訪問(wèn)實(shí)例成員在實(shí)例方法中:可以直接訪問(wèn)實(shí)例成員調(diào)用前初始化(*)實(shí)例化對(duì)象時(shí)初始化(*).部分類也可以定義部分方法。部分方法在部分類中定義,但沒有方法體,在另ー個(gè)部分類中執(zhí)行。在這兩個(gè)部分類中,都要使用partial關(guān)鍵字。publicpartialclassMyClass(partialvoidMyPartialMethodO;)publicpartialclassMyClass(partialvoidMyPartialMethod()(//Methodimplementation)}部分方法也可以是靜態(tài)的,但它們總是私有的,且不能有返回值。它們使用的任何參數(shù)都不能是out參數(shù),但可以是ref參數(shù)。部分方法還不能使用virtual、abstract、override、new、sealed和extern修飾符。有了這些限制,就不太容易看出部分方法的作用了。實(shí)際上,部分方法在編譯代碼時(shí)非常重要,其用法倒并不重要。考慮下面的代碼:publicpartialclassMyClass(partialvoidDoSomethingElse();publicvoidDoSomethingOConsole.WriteLine(uDoSomething()executionstarted.);DoSomethingElse();Console.WriteLine("DoSomething()executionfinished.n);i)publicpartialclassMyClass(partialvoidDoSomethingElse()(Console.WriteLine("DoSomethingElse()called.n);I:這段代碼定義了部分方法DoSomethingElse,在第一個(gè)部分類中定義,在第二個(gè)部分類中執(zhí)行〇在控制臺(tái)應(yīng)用程序中調(diào)用DoSomething時(shí),輸出如下所示:DoSomething()executionstarted.DoSomethingElse()called.DoSomething()executionfinished.如果刪除第二個(gè)部分類定義,或者刪除部分方法的全部執(zhí)行代碼(注釋掉代碼),輸出就如下所示:DoSomething()executionstarted.讀者可能認(rèn)為,調(diào)用DoSomethingElse時(shí),運(yùn)行庫(kù)發(fā)現(xiàn)該方法沒有執(zhí)行代碼,因此會(huì)繼續(xù)執(zhí)行下一行代碼。但實(shí)際上,編譯代碼時(shí),如果代碼包含ー個(gè)沒有執(zhí)行代碼的部分方法,編譯器會(huì)完全刪除該方法,還會(huì)刪除對(duì)該方法的所有調(diào)用。執(zhí)行代碼時(shí),不會(huì)檢查執(zhí)行代碼,因?yàn)闆]有檢查方法的調(diào)用。這會(huì)略微提高性能。與部分類ー樣,在定制自動(dòng)生成的代碼或設(shè)計(jì)器創(chuàng)建的代碼時(shí),部分方法是很有用的。設(shè)計(jì)器會(huì)聲明部分方法,用戶根據(jù)具體情形選擇是否執(zhí)行它。如果不執(zhí)行它,就不會(huì)影響性能,因?yàn)樵摲椒ㄔ诰幾g過(guò)的代碼中不存在。.訪問(wèn)權(quán)限訪問(wèn)修飾符:public:可以在任何地方被訪問(wèn)internal:只能在本項(xiàng)目中被訪問(wèn)(在類這個(gè)級(jí)別,不寫訪問(wèn)修飾符時(shí)默認(rèn)的)private:只能在本類中被訪問(wèn)(在類中跟方法中不寫訪問(wèn)修飾符時(shí)所默認(rèn)的)preotectd:只能在本類和子類中被訪問(wèn)protectedinternal:修飾的屬性/方法只能在它的在同一個(gè)程序集中的子類被訪問(wèn)不在同一個(gè)命名空間下的類,不能直接訪問(wèn),有2種方法可以訪問(wèn):1.通過(guò)using引用的命名空間。2.寫全稱.命名空間.類名在靜態(tài)方法中,只能訪問(wèn)靜態(tài)屬性,不能直接訪問(wèn)實(shí)例屬性。在static成員中不能直接調(diào)用非static成員,在非static成員中可以調(diào)用static成員。私有成員也會(huì)被繼承,但是不能被訪問(wèn)。一般用private修飾后讓他們看上去似乎是不能被繼承的,但實(shí)際上確實(shí)被繼承了。6.接口(interface)只含有共有抽象方法(publicabstractmethod)的類〇這些方法必須在子類中被實(shí)現(xiàn)。定義接口的一般形式為:[attributes][modifiers]interfaceidentifier[:base-list]{interface-body}[;]說(shuō)明:1、attributes(可選):附加的定義性信息。2、modifiers(可選):允許使用的修飾符有new和四個(gè)訪問(wèn)修飾符。分別是:new、public、protected、internal、privateo在ー個(gè)接口定義中同一修飾符不允許出現(xiàn)多次,new修飾符只能出現(xiàn)在嵌套接口中,表示覆蓋了繼承而來(lái)的同名成員。Thepublic,protected,internal,andprivate修飾符定義了對(duì)接ロ的訪問(wèn)權(quán)限。3、identifier:接口名稱。4、base-list(可選):包含一個(gè)或多個(gè)顯式基接口的列表,接口間由逗號(hào)分隔。5、interface-body:接口主體,ー個(gè)接口的接口主體定義接口的成員。6、接ロ可以是命名空間或類的成員,并且可以包含下列成員的簽名:方法、屬性、索引器.7、ー個(gè)接口可從ー個(gè)或多個(gè)基接口繼承。如:interfaceIMyExample{stringthis[intindex]{get;set;}eventEventHandlerEvenvoidFind(intvalue);stringPoint{get;set;}ipublicdelegatevoidEventHandler(objectsender,Evente);上面例子中的接口包含ー個(gè)索引this、一個(gè)事件Even、ー個(gè)方法Find和一個(gè)屬性Point。C#中接口和類的異同:接口和類都是類,不同的是,接口只包含方法或?qū)傩缘穆暶?不包含具體實(shí)現(xiàn)方法的代碼,接口可以實(shí)現(xiàn)多繼承,而類只能是單繼承,繼承接口的類必須實(shí)現(xiàn)接口中聲明的方法或?qū)傩?。接口是一個(gè)純粹的抽象類,沒有任何實(shí)際的東西,只是定義了一個(gè)框架,而抽象類里面可以有實(shí)際的ー個(gè)方法,并不要求所有的方法都是抽象的??梢詫?shí)現(xiàn)ー個(gè)接口中的所有方法,也可以繼承一個(gè)抽象的類,然后覆寫其中的方法。接ロー般只有方法,而沒有數(shù)據(jù)成員或?qū)傩?。抽象類有方?也有數(shù)據(jù)成員或?qū)傩?一般情況下,優(yōu)先考慮用接口,只有當(dāng)可能要訪問(wèn)到數(shù)據(jù)成員或?qū)傩詴r(shí),用抽象類。接口是抽像類的變體。在接口中,所有方法都是抽像的。多繼承性可通過(guò)實(shí)現(xiàn)這樣的接口而獲得。接口中的所有方法都是抽像的,沒有一個(gè)有程序體。接口只可以定義staticfinal成員變量。接口可以繼承接口。接口的成員不能使用internal修飾符。接口可以包含屬性、方法、索引指示器和事件,但不能包含常量、域、操作符、構(gòu)造函數(shù)和析構(gòu)函數(shù),而且也不能包含任何靜態(tài)成員。接口好比ー種模版,這種模版定義了對(duì)象必須實(shí)現(xiàn)的方法,其目的就是讓這些方法可以作為接口實(shí)例被引用。接口不能被實(shí)例化。類可以實(shí)現(xiàn)多個(gè)接ロ并且通過(guò)這些實(shí)現(xiàn)的接口被索引。接口變量只能索引實(shí)現(xiàn)該接口的類的實(shí)例。C#中的接口與類不同,可以使用多繼承,即ー個(gè)子接口可以有多個(gè)父接口。但如果兩個(gè)父成員具有同名的成員,就產(chǎn)生了二義性(這也正是C#中類取消了多繼承的原因之一),這時(shí)在實(shí)現(xiàn)時(shí)最好使用顯式的聲明示例:usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceExamplel7(classProgram]〃ー個(gè)完整的接口聲明示例interfacelExample{〃屬性stringP{get;set;〃方法stringF(intValue);〃事件eventEventHandlerE;〃索引指示器stringthis[intIndex]{get;set;)interfaceIA{'intCount{get;set;}]interfaceIB{intCount();i〃IC接口從IA和IB多重繼承interfaceIC:IA,IBclassC:ICprivateintcount=100;〃顯式聲明實(shí)現(xiàn)IA接口中的Count屬性intIA.Count{get{return100;}set{count=value;})〃顯式聲明實(shí)現(xiàn)IB接口中的Count方法intIB.Count(){returncount*count;}IstaticvoidMain(stringロargs){CtmpObj=newC();〃調(diào)用時(shí)也要顯式轉(zhuǎn)換Console.WriteLine〈Countproperty-{〇},
((IA)tmpObj).Count);Console.WriteLine(Countfunction-{0},((IB)tmpObj).Count());Console.ReadLineO;結(jié)果:Countproperty:100Countfunction:100007.認(rèn)識(shí)類圖PersonClass金字段」屬性ヨ金字段」屬性ヨ▼PersonOTeacherClassTeacherClassPersonと字段マ屬性サSalary:int才YearsOfServlce:intコ方法SayHi0:voidTeacher0StudentClassPerson五字段屬性ザHobby:string"TPopularity:int,方法MSayHl0:voidVStudent()通用類圖類名Student■age;int
?name;string
+Name:string+SayHi():yoid8.New關(guān)鍵字可以在派生類中隱蔵基類的方法,也就說(shuō)在使用派生類的方法是調(diào)用的方法是C#New關(guān)鍵字新定義出來(lái)的方法,而不是基類的方法。在不使用C#New關(guān)鍵字來(lái)隱蔵基類方法也是可以的,編譯器會(huì)出現(xiàn)ー個(gè)警告,提示如果有意去隱藏基類的方法,請(qǐng)使用C#New關(guān)鍵字修飾。學(xué)習(xí)難點(diǎn)String可以看做是char的只讀數(shù)組,String的字符串的重要特性,不可變型,即字符串一旦聲明就不可改變。所以只能通過(guò)索引來(lái)讀取指定位置的char,不能對(duì)指定位置char進(jìn)行修改。要想修改可以用以下方式實(shí)現(xiàn):Strings="heklo”;char[]arr=s.ToCharArray();arr[2]="1";String是密封類,所以不能被繼承。String有l(wèi)ength。這個(gè)方法。數(shù)組沒有l(wèi)ength()這個(gè)方法,但有l(wèi)ength的屬性。當(dāng)我們實(shí)例化一個(gè)類時(shí),系統(tǒng)會(huì)自動(dòng)對(duì)這個(gè)類的屬性進(jìn)行初始化,數(shù)字類型初始為〇/〇?〇,string類型初始為null,char類型初始為:¥0。int,datetime,bool,char等類型都屬于值類型(ValueType),賦值的時(shí)候是傳遞拷貝。普通的對(duì)象則是引用類型,賦值的時(shí)候是傳遞引用。如:inti=10;intj;i++;Console.WriteLine(j);輸出10Personpl=newPerson(lO);Personp2=pl;pl.Age++;Console.WriteLine(p2.Age);輸出11const和readonly有什么區(qū)別?答:const可以用于類的成員常量和局部常量,必須在聲明時(shí)賦值,之后不可以對(duì)常量進(jìn)行賦值。而readonly只能用于類的成員變量不能用于局部變量,在聲明時(shí)可以不賦值,除了在構(gòu)造函數(shù)中可以再次賦值外,其它的地方和constー樣也不能賦值。接口和抽象類有什么區(qū)別?你選擇使用接口和抽象類的依據(jù)是什么?答:(1)抽象類可以有抽象成員(無(wú)具體實(shí)現(xiàn)),也可以有非抽象成員(有具體實(shí)現(xiàn));接口只有抽象成員。(2)一個(gè)類不能同時(shí)繼承多個(gè)抽象類,ー個(gè)類可以同時(shí)實(shí)現(xiàn)多個(gè)接口。如果多個(gè)子類中有很多代碼是重復(fù)的,這時(shí)采用抽象類,因?yàn)榭梢詫⑦@些代碼放到抽象類的非抽象方法中,這樣可以達(dá)到代碼復(fù)用。當(dāng)實(shí)現(xiàn)多個(gè)接口時(shí)因?yàn)槌橄箢惒恢С?只能使用接口。.成員變量和成員函數(shù)前加static的作用?答:它們被稱為常成員變量和常成員函數(shù),又稱為類成員變量和類成員函數(shù)。分別用來(lái)反映類的狀態(tài)。比如類成員變量可以用來(lái)統(tǒng)計(jì)類實(shí)例的數(shù)量,類成員函數(shù)負(fù)責(zé)這種統(tǒng)計(jì)的動(dòng)作。.為什么不能指定接口中方法的修飾符?接口中的方法用來(lái)定義對(duì)象之間通信的契約,指定接口中的方法為私有或保護(hù)沒有意義。他們默認(rèn)為公有方法。常見企業(yè)面試題1.classPerson1(intage;publicintAgeset{}get{return18;}IIstaticvoidMain(string[]args){Personlpl=newPerson1();pl.Age=30;pl.Age=pl.Age+1;Console.WriteLine(pl.Age);}(輸出I8)classPerson2intage;publicintAge(set(this.Age=value;]get{returnthis.Age;]}staticvoidMain(string[]args){Person2p2=newPerson2();p2.Age=30;Console.WriteLine(p2.Age);I(死循環(huán),自己給自己賦值,應(yīng)p2.age=30)2.以下程序有什么錯(cuò)?publicclassTestClassprivateintcount;privatestaticinty;publicstaticvoidsetvalue()(count=l;y=i;})答:在靜態(tài)函數(shù)中只能訪問(wèn)靜態(tài)成員變量;以上代碼訪問(wèn)了實(shí)例成員。.傳值和傳引用,傳引用又兩種方式,ref和out,ref要求變量在傳參前賦值,out可以不賦值。傳引用必須是ー個(gè)地址,傳值是指將棧中的值拷貝到函數(shù)的參數(shù),傳引用表示傳入的變量和接收參數(shù)是同一個(gè)變量publicclassTest{publicintmyVar;publicintMyProperty(get{returnmyVar;}set{myVar=value;})}以上這個(gè)類中有字段和屬性i=100;有一個(gè)方法傳遞引用,調(diào)用方式如下Testt=newTest();F(reft.MyProperty);以上代碼編譯不能通過(guò),因?yàn)閷傩圆皇亲兞?其實(shí)質(zhì)是函數(shù),如下則可通過(guò)Testt=newTest();F(reft.myVar);因?yàn)樽侄问亲兞?能夠?qū)⒎庆o態(tài)的方法覆寫成靜態(tài)方法么?不能,覆寫方法的簽名必須與被覆寫方法的簽名保持一致,除了將virtual改為override。.可以覆寫私有的虛方法么?不可以,甚至子類中無(wú)法訪問(wèn)父類中的私有方法。.能夠?qū)崿F(xiàn)允許某個(gè)類被繼承,但不允許其中的某個(gè)方法被覆寫么?可以,標(biāo)記這個(gè)類為public,并標(biāo)記這個(gè)方法為sealed。.Strings=newString("xyz”);創(chuàng)建了幾個(gè)StringObject?答:兩個(gè)對(duì)象,ー個(gè)是"xyz",ー個(gè)是指向"xyz”的引用對(duì)象s。8,在C#中,stringstr=null與stringstr=" "有何區(qū)別?答:stringstr=null是不給他分配內(nèi)存空間,而stringstr="”給它分配長(zhǎng)度為空字符串的內(nèi)存空間.publicstaticintCount=0;staticClassi()(Count++;}publicClassi()(Count++;))Classiol=newClassi();Classio2=newClassi();請(qǐng)問(wèn),Classi.Count的值是多少?().以下哪些可以作為接口成員?(多選)A.方法B.屬性C.字段D.事件E.索引器F.構(gòu)造函數(shù)G.析構(gòu)函數(shù)(答案ABDE).abstractclassBaseClass(publicvirtualvoidMethodAO(IpublicvirtualvoidMethodBOclassClassi-BaseClass(publicvoidMethodA(stringarg)publicoverridevoidMethodB())classClass2'Classi(newpublicvoidMethodB()(classMainClass(publicstaticvoidMain(string[]args)(Class2〇二newClass2();Console.WriteLine(o.MethodA());)請(qǐng)問(wèn),o.MethodA調(diào)用的是:(A)BaseClass.MethodAClass2,MethodAClassi.MethodAD,都不是集合、比較和轉(zhuǎn)換前面討論了C#中所有的基本OOP技術(shù),讀者還應(yīng)熟悉ー些比較高級(jí)的技術(shù)。本章的主要內(nèi)容如ド:集合:集合可以維護(hù)對(duì)象組。與前面章節(jié)使用的數(shù)組不同,集合可以包含更高級(jí)的功能,例如,控制對(duì)它們包含的對(duì)象的訪問(wèn)、搜索和排序等。本章將介紹如何使用和創(chuàng)建集合類,學(xué)習(xí)掌握它們的ー些強(qiáng)大技術(shù)。比較:在處理對(duì)象時(shí),常常要比較它們。這對(duì)于集合尤其重要,因?yàn)檫@是排序的實(shí)現(xiàn)方式。本章將介紹如何以各種方式比較對(duì)象,包括運(yùn)算符重載,使用IComparable和IComparer接口對(duì)集合排序。轉(zhuǎn)換:在前面的章節(jié)中,介紹了如何把對(duì)象從ー種類型強(qiáng)制轉(zhuǎn)換為另ー種類型。本章討論如何定制類型轉(zhuǎn)換,以滿足自己的要求。集合第5章介紹了如何使用數(shù)組創(chuàng)建包含許多對(duì)象或值的變量類型。但數(shù)組有一定的限制。最大的限制是一旦創(chuàng)建好數(shù)組,它們的大小就是固定的,不能在現(xiàn)有數(shù)組的末尾添加新項(xiàng),除非創(chuàng)建一個(gè)新的數(shù)組。這常常意味著用于處理數(shù)組的語(yǔ)法比較復(fù)雜。OOP技術(shù)可以創(chuàng)建在內(nèi)部進(jìn)行這些處理的類,因此簡(jiǎn)化了使用項(xiàng)列表或數(shù)組的代碼。C#中的數(shù)組實(shí)現(xiàn)為System.Array類的實(shí)例,它們只是集合類中的ー種。集合類一般用于處理對(duì)象列表,其功能比簡(jiǎn)單數(shù)組要多,這些功能是通過(guò)實(shí)現(xiàn)System.Collections名稱空間中的接口而獲得的,因此集合的語(yǔ)法已經(jīng)標(biāo)準(zhǔn)化了。這個(gè)名稱空間還包含其他ー些有趣的東西,例如,以與System.Array不同的方式實(shí)現(xiàn)這些接口的類。集合的功能(包括基本函數(shù),例如,用[index]語(yǔ)法訪問(wèn)集合中的項(xiàng))可以通過(guò)接口來(lái)實(shí)現(xiàn),該接口不僅沒有限制我們使用基本集合類,例如System.Array,相反,我們還可以創(chuàng)建自己的定制集合類。這些集合可以專用于要枚舉的對(duì)象(即要從中建立集合的對(duì)象)。這么做的一個(gè)優(yōu)點(diǎn)是定制的集合類可以是強(qiáng)類型化的。也就是說(shuō),從集合中提取項(xiàng)時(shí),不需要把它們轉(zhuǎn)換為正確的類型。另ー個(gè)優(yōu)點(diǎn)是提供專用的方法,例如,可以提供獲得項(xiàng)子集的快捷方法,在撲克牌示例中,可以添加一個(gè)方法,獲得特定suit中的所有Card項(xiàng)。
System.Collections名稱空間中的幾個(gè)接口提供了基本的集合功能:lEnumerable可以迭代集合中的項(xiàng)。[Collection(繼承于【Enumerable)可以獲取集合中項(xiàng)的個(gè)數(shù),并能把項(xiàng)復(fù)制到ー?個(gè)簡(jiǎn)單的數(shù)組類型中。IList(繼承于lEnumerable和【Collection)提供了集合的項(xiàng)列表,并可以訪問(wèn)這些項(xiàng),以及其他ー些與項(xiàng)列表相關(guān)的功能?!綝ictionary(繼承于【Enumerable和【Collection)類似于【List,但提供r可通過(guò)鍵碼值而不是索引訪問(wèn)的項(xiàng)列表。System.Array類實(shí)現(xiàn)了【しist、【Collection和【Enumerable,但不支持IList的ー一些更高級(jí)的功能,它表示大小固定的項(xiàng)列表。使用集合Systems.Collections名稱空間中的類System.Collections.ArrayList也實(shí)現(xiàn)了【List、ICollection和!Enumerable接口,但實(shí)現(xiàn)的方式比System.Array更復(fù)雜。數(shù)組的大小是固定的(不能增加或刪除元素),而這個(gè)類可以用于表示大小可變的項(xiàng)列表。為了更準(zhǔn)確地理解這個(gè)高級(jí)集合的功能,下面介紹一個(gè)使用這個(gè)類和一個(gè)簡(jiǎn)單數(shù)組的示例。試試看:數(shù)組和高級(jí)集合(1)在目錄C:\BegVCSharp\Chapterl1'下倉(cāng)リ建一個(gè)新的控制臺(tái)應(yīng)用程序ChllExOlo(2)在SolutionExplorer窗口中右擊項(xiàng)目,選擇AddIClass選項(xiàng),給項(xiàng)目添加3個(gè)新類:Animal>Cow和Chicken。(3)修改Animal.cs中的代碼,如下所示:namespaceChilExOlpublicabstractclassAnimal
protectedstringname;publicstringName(get{returnname;}set(name=value;}}publicAnimal()(name="Theanimalwithnoname";}publicAnimal(stringnewName)(name=newName;}publicvoidFeed()Console.WriteLine("{0}hasbeenfed?”,name);⑷修改Cow.cs中的代碼,如下所示:namespaceChllExOl(publicclassCow:Animal{publicvoidMilk()(Console.WriteLine("{0}hasbeenmilked.",name);)publicCow(stringnewName):base(newName)()}}⑸修改Chicken.cs中的代碼,如下所示:namespaceChllExOl{publicclassChicken:Animal{publicvoidLayEgg()(Console.WriteLine(n{0}haslaidanegg.”,name);publicChicken(stringnewName):base(newName)))(6)修改Program.es中的代碼,如下所示:usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespaceChllExOl{classProgram{staticvoidMain(string[]args)(Console.WriteLine("CreateanArraytypecollectionofAnimal"objectsanduseit:");Animal[]animalArray=newAnimal[2];CowmyCowl=newCow("Deirdre");animalArray[0]=myCowl;animalArray[1]=newChicken("Ken");foreach(AnimalmyAnimalinanimalArray)Console.WriteLine(nNew{0}objectaddedtoArraycollection,n+"Name={1}",myAnimal.ToString(),myAnimal.Name);)Console.WriteLine("Arraycollectioncontains{0}objects.",animalArray.Length);animalArray[0].Feed();((Chicken)animalArray[1]).LayEgg();Console.WriteLine();Console.WriteLine("CreateanArrayListtypecollectionofAnimal"+"objectsanduseit:");ArrayListanimalArrayList=newArrayList();CowmyCow2=newCow("Hayley");animalArrayList.Add(myCow2);animalArrayList.Add(newChicken("Roy"));foreach(AnimalmyAnimalinanimalArrayList)(Console.WriteLine("New{0}objectaddedtoArrayListcollection,"+"Name={1}",myAnimal.ToString(),myAnimal.Name);}Console.WriteLine("ArrayListcollectioncontains{0}objects,”,animalArrayList.Count);((Animal)animalArrayList[0]).Feed();((Chicken)animalArrayList[1]).LayEgg();Console.WriteLine();Console.WriteLine("AdditionalmanipulationofArrayList:");animalArrayList.RemoveAt(0);((Animal)animalArrayList[0]).Feed();animalArrayList.AddRange(animalArray);((Chicken)animalArrayList[2]).LayEgg();Console.WriteLine("Theanimalcalled{0}isatindex{1}."zmyCowl.Name,animalArrayList.IndexOf(myCowl));myCowl.Name="Janice";Console.WriteLine("Theanimalisnowcalled{0}.",((Animal)animalArrayList[1]).Name);Console.ReadKey();)}}(7)運(yùn)行該應(yīng)用程序,其結(jié)果如圖!1-I所示SSfile://^::/Users/Kar1i/AppData/Local/TemporaryProjects/Chl1Ex01/bin/Debug/Ch11Ex01.EXECreateanfirraytypecollectionoffinInalobjectsanduseit:NewChllExOl.Cowobjectaddedtofirraycollection,Naroe=DeirdreNewChllEx01.ChickenobjectaddedtoArraycollection.Name=Kenfirraycollectioncontains2objects.Deirdrehasbeenfed.Kenhaslaidanegg.CreateanfirrayListtypecollectionoffinimalobjectsanduseit:NewChllEx01.CowobjectaddedtofirrayListcollection*Nane=HayleyNewChllEx01.ChickenobjectaddedtofirrayListcollection.Name-RoyfirrayListcollectioncontains2objects.Hayleyhasbeenfed.Royhaslaidanegg.fidditionalmanipulationoffirrayList:Royhasbeenfed.Kenhaslaidaneg”TheanimalcalledDeirdreisatindex1.TheanimalisnowcalledJanice.圖11-1示例的說(shuō)明這個(gè)示例創(chuàng)建了兩個(gè)對(duì)象集合,第一個(gè)集合使用System.Array類(這是ー個(gè)簡(jiǎn)單的數(shù)組),第二個(gè)集合使用System.Collections.ArrayList類。這兩個(gè)集合都是Animal對(duì)象,在Animal.cs中定義。Anima!類是抽象類,所以不能進(jìn)行實(shí)例化。但通過(guò)多態(tài)性(詳見第8章),可以使集合中的項(xiàng)成為派生于Animal類的Cow和Chicken類實(shí)例。這些數(shù)組在Classl.cs的Main。方法中創(chuàng)建好后,就可以顯示其特性和功能。有幾個(gè)處理操作可以應(yīng)用到Array和ArrayList集合上,但它們的語(yǔ)法略有區(qū)別。也有ー些操作只能使用更高級(jí)的ArrayList類型。下面首先通過(guò)比較這兩種集合的代碼和結(jié)果,討論一下這兩種集合的類似操作。首先是集合的創(chuàng)建。對(duì)于簡(jiǎn)單的數(shù)組來(lái)說(shuō),必須用固定的大小來(lái)初始化數(shù)組,才能使用它。下面使用第5章介紹的標(biāo)準(zhǔn)語(yǔ)法創(chuàng)建數(shù)組animalArray:Animal[]animalArray=newAnimal[2];而ArrayList集合不需要初始化其大小,所以可以使用下面的代碼創(chuàng)建列表animalArrayList:ArrayListanimalArrayList=newArrayList();這個(gè)類還有另外兩個(gè)構(gòu)造函數(shù)。第一個(gè)構(gòu)造函數(shù)把現(xiàn)有的集合作為ー個(gè)參數(shù),把現(xiàn)有集合的內(nèi)容復(fù)制到新實(shí)例中;而另ー個(gè)構(gòu)造函數(shù)通過(guò)ー個(gè)參數(shù)設(shè)置集合的容量(capacity)。這個(gè)容量用ー個(gè)int值指定,設(shè)置集合中可以包含的項(xiàng)數(shù)。但這并不是真實(shí)的容量,因?yàn)槿绻现械捻?xiàng)數(shù)超過(guò)了這個(gè)值,容量就會(huì)自動(dòng)增大一倍。因?yàn)閿?shù)組是引用類型(例如,Animal和Animal派生的對(duì)象),所以用ー個(gè)長(zhǎng)度初始化數(shù)組并沒有初始化它所包含的項(xiàng)。要使用ー個(gè)指定的項(xiàng),該項(xiàng)還需要初始化,即需要給這個(gè)項(xiàng)賦予初始化了的對(duì)象:CowmyCowl=newCow("Deirdre");animalArray[0]=myCowl;animalArray[1]=newChicken("Ken");這段代碼以兩種方式完成該初始化任務(wù):用現(xiàn)有的Cow對(duì)象來(lái)賦值,或者通過(guò)創(chuàng)建一個(gè)新的Chicken對(duì)象來(lái)賦值。主要的區(qū)別是前者引用了數(shù)組中的對(duì)象一我們?cè)诖a的后面就使用了這種方式。對(duì)于ArrayList集合,它沒有現(xiàn)成的項(xiàng),也沒有null引用的項(xiàng)。這樣就不能以相同的方式給索引賦予新實(shí)例。我們使用ArrayList對(duì)象的Add()方法添加新項(xiàng):CowmyCow2=newCow("Hayley");animalArrayList.Add(myCow2);animalArrayList.Add(newChicken("Roy"));除了語(yǔ)法略有不同外,還可以用相同的方式把新對(duì)象或現(xiàn)有的對(duì)象添加到集合中。以這種方式添加完項(xiàng)后,就可以使用與數(shù)組相同的語(yǔ)法來(lái)重寫它們,例如:animalArrayList[0]=newCow("Alma");但不能在這個(gè)示例中這么做。第5章介紹了如何使用foreach結(jié)構(gòu)迭代一個(gè)數(shù)組。這是可以的,因?yàn)镾ystem.Array類實(shí)現(xiàn)了【Enumerable接口,這個(gè)接口的唯一方法GetEnumerator。可以迭代集合中的各項(xiàng)。后面將詳細(xì)討論這一點(diǎn)。在代碼中,我們寫出了數(shù)組中每個(gè)Animal對(duì)象的信息:foreach(AnimalmyAnimalinanimalArray)Console.WriteLine("New{0}objectaddedtoArraycollection,"Name={1}",myAnimal.ToString(),myAnimal.Name);)這里使用的ArrayList對(duì)象也支持IEnumerable接口,并可以與foreach一I起使用,此時(shí)語(yǔ)法是相同的:foreach(AnimalmyAnimalinanimalArrayList){Console.WriteLine("New{0}objectaddedtoArrayListcollection,"+"Name={1}",myAnimal.ToString(),myAnimal.Name);}接著,使用數(shù)組的Length屬性,在屏幕上輸出數(shù)組中元素的個(gè)數(shù):Console.WriteLine("Arraycollectioncontains{0}objects.",animalArray.Length);也可以使用ArrayList集合得到相同的結(jié)果,但要使用Count屬性,該屬性是【Collection接口的一部分:Console.WriteLine("ArrayListcollectioncontains{0}objects.",animalArrayList.Count);集合一無(wú)論是簡(jiǎn)單的數(shù)組,還是比較復(fù)雜的集合一都用得不多,除非它們可以訪問(wèn)屬于它們的項(xiàng)。簡(jiǎn)單數(shù)組是強(qiáng)類型化的,可以直接訪問(wèn)它們所包含的項(xiàng)類型。所以可以直接調(diào)用項(xiàng)的方法:animalArray[0].Feed();數(shù)組的類型是抽象類型Animal,因此不能直接調(diào)用由派生類提供的方法,而必須使用數(shù)據(jù)類型轉(zhuǎn)換:((Chicken)animalArray[1]).LayEgg();ArrayList集合是System.Object對(duì)象的集合(通過(guò)多態(tài)性賦給Anima!對(duì)象),陰U必須對(duì)所有的項(xiàng)進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換:((Animal)animalArrayList[0]).Feed();((Chicken)animalArrayList[1]).LayEgg();代碼的剩余部分利用的ー些ArrayList集合功能超出了Array集合的功能范圍。首先,可以使用Remove。和RemoveAt。方法刪除項(xiàng),這兩個(gè)方法是在ArrayList類中實(shí)現(xiàn)的IList接口的一部分。它們分別根據(jù)項(xiàng)目引用或索引把項(xiàng)從數(shù)組中刪除。在本例中,我們使用后ー個(gè)方法刪除添加到列表中的第一項(xiàng),即Name屬性為Hayley的Cow對(duì)象:animalArrayList.RemoveAt(0);另外,還可以使用:animalArrayList.Remove(myCow2);因?yàn)檫@個(gè)對(duì)象已經(jīng)有一個(gè)本地引用了,所以可以通過(guò)Add()添加對(duì)數(shù)組的ー個(gè)現(xiàn)有引用,而不是創(chuàng)建一個(gè)新對(duì)象。無(wú)論采用哪種方式,集合中唯一剩下的項(xiàng)是Chicken對(duì)象,可以用下面的方式訪問(wèn)它:((Animal)animalArrayList[0]).Feed();對(duì)ArrayList對(duì)象中的項(xiàng)進(jìn)行修改,使數(shù)組中剩下N個(gè)項(xiàng),其實(shí)現(xiàn)方式與保留從0-N-1的索引相同。例如,刪除索引為〇的項(xiàng),會(huì)使其他項(xiàng)在數(shù)組中移動(dòng)ー個(gè)位置,所以應(yīng)使用索引0來(lái)訪問(wèn)Chicken對(duì)象,而不是I。不再有索引為1的項(xiàng)了(因?yàn)榧现凶畛踔挥袃蓚€(gè)項(xiàng)),所以如果試圖執(zhí)行下面的代碼,就會(huì)拋出異常:((Animal)animalArrayList[1]).Feed();ArrayList集合可以用AddRange。方法一次添加好幾個(gè)項(xiàng)。這個(gè)方法接受帶有ICollection接口的任何對(duì)象,包括前面的代碼所創(chuàng)建的animalArray數(shù)組:animalArrayList.AddRange(animalArray);為了確定這是否有效,可以試著訪問(wèn)集合中的第三項(xiàng),它將是animalArray中的第二項(xiàng):((Chicken)animalArrayList[2]).LayEgg();AddRange。方法不是ArrayList提供的任何接口的一部分。這個(gè)方法專用于ArrayList類,論證了可以在集合類中執(zhí)行定制操作,而不僅僅是前面介紹的接口要求的操作。這個(gè)類還提供了其他有趣的方法,如InsertRange。,它可以把數(shù)組對(duì)象插入到列表中的任何位置,還有用于給數(shù)組排序和重新排序的方法。最后,再回過(guò)頭來(lái)看看對(duì)同一個(gè)對(duì)象進(jìn)行多個(gè)引用。使用IList接口中的!ndexOf。方法可以看出,myCowl(最初添加到animalArray中的ー個(gè)對(duì)象)現(xiàn)在是animalArrayList集合的一部分,它的索引如下:Console.WriteLine(nTheanimalcalled{0}isatindex{1}.n,myCowl.Name,animalArrayList.IndexOf(myCowl));例如,接下來(lái)的兩行代碼通過(guò)對(duì)象引用重新命名了對(duì)象,并通過(guò)集合引用顯示了新名稱:myCowl.Name=nJanice";Console.WriteLine("Theanimalisnowcalled{0}.",((Animal)animalArrayList[1]).Name);定義集合前面介紹了使用高級(jí)集合類能完成什么任務(wù),下面討論如何創(chuàng)建自己的、強(qiáng)類型化的集合。ー種方式是手動(dòng)執(zhí)行需要的方法,但這比較花時(shí)間,在某些情況下也非常復(fù)雜。我們還可以從ー個(gè)類中派生自己的集合,例如System.Collections.CollectionBase類,這個(gè)抽象類提供了集合類的許多實(shí)現(xiàn)方式。這是推薦使用的方式。CollectionBase類有接口【Enumerable、ICollection和IList,但只提供了一些要求的執(zhí)行代碼,特別是IList的Clear。和RemoveAt。方法,以及!Collection的Count屬性。如果要使用提供的功能,就需要自己執(zhí)行其他代碼。為了便于完成任務(wù),CollectionBase提供了兩個(gè)受保護(hù)的屬性,它們可以訪問(wèn)存儲(chǔ)的對(duì)象本身。我們可以使用List和!nnerList,List可以通過(guò)!List接口訪問(wèn)項(xiàng),InnerList則是用于存儲(chǔ)項(xiàng)的ArrayList對(duì)象。例如,存儲(chǔ)Animal對(duì)象的集合類可以定義如下(稍后介紹ー個(gè)比較完整的執(zhí)行代碼):publicclassAnimals:CollectionBase(publicvoidAdd(AnimalnewAnimal)(List.Add(newAnimal);)publicvoidRemove(AnimaloldAnimal)(List.Remove(oldAnimal);)publicAnimals()())其中,Add。和Remove。方法實(shí)現(xiàn)為強(qiáng)類型化的方法,使用IList接口中用于訪問(wèn)項(xiàng)的標(biāo)準(zhǔn)Add。方法。該方法現(xiàn)在只用于處理Anima!類或派生于Animal的類,而前面介紹的ArrayList執(zhí)行代碼可處理任何對(duì)象。CollectionBase類可以對(duì)派生的集合使用foreach語(yǔ)法。例如,可以使用下面的代碼:Console.WriteLine("UsingcustomcollectionclassAnimals:");AnimalsanimalCollection=newAnimals();animalCollection.Add(newCow("Sarah"));foreach(AnimalmyAnimalinanimalCollection)(Console.WriteLine("New{0}objectaddedtocustomcollection,"+"Name={1}",myAnimal.ToString(),myAnimal.Name);)但不能使用下面的代碼:animalCollection[0].Feed();要以這種方式通過(guò)索引來(lái)訪問(wèn)項(xiàng),就需要使用索引符。索引符索引符(indexer)是一種特殊類型的屬性,可以把它添加到ー個(gè)類中,以提供類似于數(shù)組的訪問(wèn)。實(shí)際上,可以通過(guò)索引符提供更復(fù)雜的訪問(wèn),因?yàn)槲覀兛梢杂梅嚼ㄌ?hào)語(yǔ)法定義和使用復(fù)雜的參數(shù)類型。它最常見的一個(gè)用法是對(duì)項(xiàng)執(zhí)行簡(jiǎn)單的數(shù)字索引。在Animal對(duì)象的Animals集合中添加一個(gè)索引符,如下所示:publicclassAnimals:CollectionBase{publicAnimalthis[intanimallndex]getreturn(Animal)List[animallndex];}set(List[animallndex]=value;)}}this關(guān)鍵字與方括號(hào)中的參數(shù)一起使用,但這看起來(lái)類似于其他屬性。這個(gè)語(yǔ)法是富有邏輯的,因?yàn)樵谠L問(wèn)索引符時(shí),將使用對(duì)象名,后跟放在方括號(hào)中的索引參數(shù)(例如MyAnimals|0])o這段代碼對(duì)しist屬性使用ー個(gè)索引符(即在IList接口上,可以訪問(wèn)CollectionBase中的ArrayList,ArrayList存儲(chǔ)了項(xiàng)):return(Animal)List[animallndex];這里需要進(jìn)行顯式數(shù)據(jù)類型轉(zhuǎn)換,因?yàn)?List.List屬性返回ー個(gè)System.Object對(duì)象。注意,我們?yōu)檫@個(gè)索引符定義了一個(gè)類型。使用該索引符訪問(wèn)某項(xiàng)時(shí),就可以得到這個(gè)類型,即可以編寫下述代碼:animaICollection[0].Feed();而不是:((Animal)animalCollection[0]).Feed();這是強(qiáng)類型化的定制集合的另ー個(gè)方便特性。下面擴(kuò)展上一個(gè)示例,實(shí)踐一下該特性。試試看:實(shí)現(xiàn)Animals集合(1)在目錄C:\BegVCSharp\Chapterl1'下倉(cāng)リ建一個(gè)新控制臺(tái)應(yīng)用程序ChllEx02o(2)在SolutionExplorer窗口中右擊項(xiàng)目名,選擇AddIExistingItem選項(xiàng)。(3)從目錄C:\BegVCSharp\Chapterll\ChllEx01\ChllExOl下選擇Animal.cs、Cow.cs和Chicken.cs文件,單擊Add按鈕。(4)修改這3個(gè)文件中的名稱空間聲明,如下所示:namespaceChllExO2(5)添加一個(gè)新類Animalso(6)修改Animals.cs中的代碼,如下所示:usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;?endregionnamespaceChllExO2(publicclassAnimals:CollectionBase{publicvoidAdd(AnimalnewAnimal)(List.Add(newAnimal);}publicvoidRemove(AnimalnewAnimal)(List.Remove(newAnimal);publicAnimals()publicAnimalthis[intanimalIndex]get(return(Animal)List[animalIndex];)set{List[animalIndex]=value;)})}(7)修改Program.es,如下所示:staticvoidMain(string[]args)(AnimalsanimalCollection=newAnimals();animalCollection.Add(newCow("Jack"));animalCollection.Add(newChicken("Vera"));foreach(AnimalmyAnimalinanimalCollection)(myAnimal.Feed();)Console.ReadKey();}(8)}(8)執(zhí)行應(yīng)用程序圖11-2示例的說(shuō)明這個(gè)示例使用上一節(jié)詳細(xì)介紹的代碼,實(shí)現(xiàn)類Animals中強(qiáng)類型化的Anima!對(duì)象集合。Main。中的代碼僅實(shí)例化了一個(gè)Animals對(duì)象animalCollection,添加了兩個(gè)項(xiàng)(它們分別是Cow和Chicken的實(shí)例),再使用foreach循環(huán)調(diào)用這兩個(gè)對(duì)象繼承于基類Anima!的Feed。方法。給CardLib添加Cards集合第!0章創(chuàng)建了一個(gè)類庫(kù)項(xiàng)目ChlOCardLib,它包含ー個(gè)表示撲克牌的Card類和ー個(gè)表示一幅撲克牌的Deck類,這個(gè)Deck類是Card類的集合,且實(shí)現(xiàn)為ー個(gè)簡(jiǎn)單的數(shù)組。本章給這個(gè)庫(kù)添加一個(gè)新類,并把類庫(kù)重命名為ChllCardLib。這個(gè)新類Cards是Card對(duì)象的ー個(gè)定制集合,并擁有本章前面介紹的各種功能。在目錄C:\BegVCSharp\Chapterl1、下創(chuàng)建一個(gè)新的類庫(kù)ChiICardLib,再?gòu)腜rojectIAddExistingItem中選擇C:\BegVCSharp\ChapterlO\ChlOCardLib\ChlOCardLib目錄下的Card.cs、Deck.cs、Suit.cs和Rank.cs文件,把它們添加到項(xiàng)目中。與第10章介紹的這個(gè)項(xiàng)目的上一個(gè)版本相同,這里也不使用標(biāo)準(zhǔn)的“試試看”格式介紹這些變化。讀者可以在本章的下載代碼中打開這個(gè)項(xiàng)目的版本,直接?xùn)丝创a。注意:在把源文件從ChlOCardLib復(fù)制到ChllCardLib中時(shí),必須修改名稱空間聲明,以引用ChllCardLib0對(duì)用于測(cè)試的ChlOCardLib控制臺(tái)應(yīng)用程序也要進(jìn)行這個(gè)修改。本章下載代碼中的ー個(gè)項(xiàng)目包含了對(duì)ChllCardLib進(jìn)行的各種擴(kuò)展。其代碼放在各個(gè)區(qū)段中,如果讀者要實(shí)踐一下,可以取消這些區(qū)段的注釋。如果要H己創(chuàng)建這個(gè)項(xiàng)目,就應(yīng)添加一個(gè)新類Cards,修改Cards.cs中的代碼,如下所示:usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespaceChllCardLib(publicclassCards:CollectionBase{publicvoidAdd(CardnewCard)(List.Add(newCard);}publicvoidRemove(CardoldCard)(List.Remove(oldCard);}publicCards()publicCardthis[intcardindex]getreturn(Card)List[cardindex];)set{List[cardindex]=value;}}//UtilitymethodforcopyingcardinstanceintoanotherCardsinstance//-usedinDeck.Shuffle().Thisimplementationassumethatsourceand//targetcollectionsarethesamesize.publicvoidCopyTo(Cardstargetcards){for(intindex=0;index<this.Count;index++)(targetcards[index]=this[index];})//ChecktoseeiftheCardscollectioncontainsaparticularcard.//ThiscallstheContainsmethodoftheArrayListforthecollection.//whichweaccessthroughtheInnerListproperty.publicboolContains(Cardcard)(returnInnerList.Contains(card);)}).然后,需要修改Deck.cs,以利用這個(gè)新集合,而不是數(shù)組:usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespaceChiICardLib{publicclassDeck{privateCardscards=newCards();publicDeck()(//lineofcoderemovedhere.for(intsuitVal=0;suitVal<4;suitVal++)(for(intrankVal=1;rankVal<14;rankVal++)cards.Add(newCard((Suit)suitVal,(Rank)rankVal));
publicCardGetCard(intcardNum)(if(cardNum>=0&&cardNum<=51)returncards[cardNum];elsethrow(newSystem.ArgumentOutOfRangeException("cardNum”,cardNum,HValuemustbebetween0and51.H));}publicvoidShuffle()(CardsnewDeck=newCards();bool[]assigned=newbool[52];RandomsourceGen=newRandom();for(inti=0;i<52;i++){intsourceCard=0;boolfoundCard=false;while(foundCard==false)(sourceCard=sourceGen.Next(52);false)if(assigned[sourceCard]==false)foundCardtruefoundCardtrue;}assigned[sourceCard]=true;newDeck.Add(cards[sourceCard]);}newDeck.CopyTo(cards,0);})}在此不需要進(jìn)行很多修改。其中的大多數(shù)修改都涉及到改變洗牌邏輯,才能把Cards中隨機(jī)的ー張牌添加到新Cards集合newDeck的開頭,而不是把cards集合中順序位置的ー張牌添加newDeck集合的隨機(jī)位置上。ChlOCardLib解決方案的客戶控制臺(tái)應(yīng)用程序ChlOCardClient可以使用這個(gè)新庫(kù)得到與以前相同的結(jié)果,因?yàn)镈eck的方法簽名沒有改變。這個(gè)類庫(kù)的客戶程序現(xiàn)在可以使用Cards集合類,而不是依賴于Card對(duì)象數(shù)組,例如,在撲克牌游戲應(yīng)用程序中定義一手牌。關(guān)鍵字值集合和【Dictionary除了IList接口外,集合還可以實(shí)現(xiàn)類似的【Dictionary接口,允許項(xiàng)通過(guò)關(guān)鍵字值(如字符串名)進(jìn)行索引,而不是通過(guò)ー個(gè)索引。這也可以使用索引符來(lái)完成,但這次的索引符參數(shù)是與存儲(chǔ)的項(xiàng)相關(guān)聯(lián)的關(guān)鍵字,而不是int索引,這樣集合的用戶友好性就更高了。與索引的集合一樣,可以使用一個(gè)基類簡(jiǎn)化IDictionaiy接口的實(shí)現(xiàn),這個(gè)基類就是DictionaryBase,它也實(shí)現(xiàn)!Enumerable和!Collection接口,提供了對(duì)任何集合都相同的集合處理功能。DictionaryBase與CollectionBaseー樣,實(shí)現(xiàn)通過(guò)其支持的接口獲得的一些成員(但不是全部成員)。DictionaryBase也執(zhí)行Clear。和Count。,但不執(zhí)行RemoveAt。。這是因?yàn)镽emoveAt。是IList接口上的ー個(gè)方法,不是いictionary接口上的一個(gè)方法。但是,Dictionary有一個(gè)Remove。方法,這是ー個(gè)應(yīng)在基于DictionaryBase的定制集合類上執(zhí)行的方法。下面的代碼是上一節(jié)Animals類的另ー個(gè)版本,這次該類派生于DictionaryBase。下面代碼包括Add。、Remove。和一個(gè)通過(guò)關(guān)鍵字訪問(wèn)的索引符的執(zhí)行代碼:publicclassAnimals:DietionaryBase{publicvoidAdd(stringnewIDzAnimalnewAnimal){Dictionary.Add(newIDznewAnimal);)publicvoidRemove(stringanimallD){Dictionary.Remove(animallD);)publicAnimals(){)publicAnimalthis[stringanimallD]{get(return(Animal)Dictionary[animallD];setDictionary[animalID]=value;))這些成員
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 建筑混凝土石料運(yùn)輸合同
- 標(biāo)準(zhǔn)存款合同范本
- 商鋪?zhàn)赓U合同解除協(xié)議格式范本
- 2024農(nóng)村建房合同范本
- 贈(zèng)與合同范本大全
- 筆記本電腦選購(gòu)協(xié)議
- 農(nóng)村土地使用權(quán)買賣合同樣本
- 房屋出租代理委托合同范本樣本
- 股票交易委托代理協(xié)議
- 代理電力收費(fèi)協(xié)議
- 《鍥而不舍金石可鏤》-完整版課件
- 《紅樓夢(mèng)》考點(diǎn)總匯
- 人教版高一英語(yǔ)必修第一冊(cè)-unit-3-reading-and-thinking-課件
- 創(chuàng)建文明城市主題班會(huì)PPT創(chuàng)建文明城市我們一起行動(dòng)PPT課件(帶內(nèi)容)
- 百變扭扭棒 課件
- 復(fù)旦大學(xué)數(shù)學(xué)物理方法講義
- 上海破產(chǎn)管理人擴(kuò)容考試參考題庫(kù)(含答案)
- 繪本課件小兔子的月亮
- 基礎(chǔ)篇1、松下電器歷史簡(jiǎn)介
- 學(xué)生餐飲方面的消費(fèi)者行為分析
- 汽車維修價(jià)格表
評(píng)論
0/150
提交評(píng)論