




已閱讀5頁,還剩18頁未讀, 繼續(xù)免費閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
目 錄第3章 對象和類型23.1 類和結(jié)構(gòu)23.2 類成員23.2.1 數(shù)據(jù)成員23.2.2 函數(shù)成員23.2.3 只讀字段143.3 匿名類型163.4 結(jié)構(gòu)163.4.1 結(jié)構(gòu)是值類型173.4.2 結(jié)構(gòu)和繼承183.4.3 結(jié)構(gòu)的構(gòu)造函數(shù)183.5 部分類183.6 靜態(tài)類193.7 Object類203.7.1 System.Object方法203.7.2 ToString()方法203.8 擴展方法223.9 小結(jié)22第3章 對象和類型到目前為止,我們介紹了組成C#語言的主要內(nèi)容,包括變量、數(shù)據(jù)類型和程序流語句,并簡要介紹了一個只包含Main()方法的完整小例子。但還沒有介紹如何把這些內(nèi)容組合在一起,構(gòu)成一個完整的程序,其關(guān)鍵就在于對類的處理。這就是本章的主題。本章的主要內(nèi)容如下:類和結(jié)構(gòu)的區(qū)別類成員按值和引用傳送參數(shù)方法重載構(gòu)造函數(shù)和靜態(tài)構(gòu)造函數(shù)只讀字段部分類靜態(tài)類Object類,其他類型都從該類派生而來第4章將介紹繼承以及與繼承相關(guān)的特性。提示:本章將討論與類相關(guān)的基本語法,但假定您已經(jīng)熟悉了使用類的基本原則,例如,知道構(gòu)造函數(shù)和屬性的含義,因此我們只是大致論述如何把這些原則應用于C#代碼。本章介紹的這些概念不一定得到了大多數(shù)面向?qū)ο笳Z言的支持。例如對象構(gòu)造函數(shù)是您熟悉的、使用廣泛的一個概念,但靜態(tài)構(gòu)造函數(shù)就是C#的新增內(nèi)容,所以我們將解釋靜態(tài)構(gòu)造函數(shù)的工作原理。3.1 類和結(jié)構(gòu)類和結(jié)構(gòu)實際上都是創(chuàng)建對象的模板,每個對象都包含數(shù)據(jù),并提供了處理和訪問數(shù)據(jù)的方法。類定義了每個類對象(稱為實例)可以包含什么數(shù)據(jù)和功能。例如,如果一個類表示一個顧客,就可以定義字段CustomerID、FirstName、LastName和Address,以包含該顧客的信息。還可以定義處理存儲在這些字段中的數(shù)據(jù)的功能。接著,就可以實例化這個類的對象,以表示某個顧客,并為這個實例設置這些字段,使用其功能。class PhoneCustomerpublic const string DayOfSendingBill =Monday;public int CustomerID;public string FirstName;public string LastName;結(jié)構(gòu)與類的區(qū)別是它們在內(nèi)存中的存儲方式(類是存儲在堆(heap)上的引用類型,而結(jié)構(gòu)是存儲在堆棧(stack)上的值類型)、訪問方式和一些特征(如結(jié)構(gòu)不支持繼承)。較小的數(shù)據(jù)類型使用結(jié)構(gòu)可提高性能。但在語法上,結(jié)構(gòu)與類非常相似,主要的區(qū)別是使用關(guān)鍵字struct代替class來聲明結(jié)構(gòu)。例如,如果希望所有的PhoneCustomer實例都存儲在堆棧上,而不是存儲在托管堆上,就可以編寫下面的語句:struct PhoneCustomerStructpublic const string DayOfSendingBill = Monday;public int CustomerID;public string FirstName;public string LastName;對于類和結(jié)構(gòu),都使用關(guān)鍵字new來聲明實例:這個關(guān)鍵字創(chuàng)建對象并對其進行初始化。在下面的例子中,類和結(jié)構(gòu)的字段值都默認為0:PhoneCustomer myCustomer = new PhoneCustomer(); /works for a classPhoneCustomerStruct myCustomer2 = new PhoneCustomerStruct(); / works for a struct在大多數(shù)情況下,類要比結(jié)構(gòu)常用得多。因此,我們先討論類,然后指出類和結(jié)構(gòu)的區(qū)別,以及選擇使用結(jié)構(gòu)而不使用類的特殊原因。但除非特別說明,否則就可以假定用于類的代碼也適用于結(jié)構(gòu)。3.2 類成員類中的數(shù)據(jù)和函數(shù)稱為類的成員。Microsoft的正式術(shù)語對數(shù)據(jù)成員和函數(shù)成員進行了區(qū)分。除了這些成員外,類還可以包含嵌套的類型(例如其他類)。類中的所有成員都可以聲明為public(此時可以在類的外部直接訪問它們)或private(此時,它們只能由類中的其他代碼來訪問)。與Visual Basic、C+和Java一樣,C#在這個方面還有變化,例如protected(表示成員僅能由該成員所在的類及其派生類訪問),第4章將詳細解釋各種訪問級別。3.2.1 數(shù)據(jù)成員數(shù)據(jù)成員包含了類的數(shù)據(jù)- 字段、常量和事件。數(shù)據(jù)成員可以是靜態(tài)數(shù)據(jù)(與整個類相關(guān))或?qū)嵗龜?shù)據(jù)(類的每個實例都有它自己的數(shù)據(jù)副本)。通常,對于面向?qū)ο蟮恼Z言,類成員總是實例成員,除非用static進行了顯式的聲明。字段是與類相關(guān)的變量。在前面的例子中已經(jīng)使用了PhoneCustomer類中的字段。一旦實例化PhoneCustomer對象,就可以使用語法Object.FieldName來訪問這些字段:PhoneCustomer Customer1 = new PhoneCustomer();Customer1.FirstName = Simon;常量與類的關(guān)聯(lián)方式同變量與類的關(guān)聯(lián)方式一樣。使用const關(guān)鍵字來聲明常量。如果它們聲明為public,就可以在類的外部訪問。class PhoneCustomerpublic const string DayOfSendingBill = Monday;public int CustomerID;public string FirstName;public string LastName;事件是類的成員,在發(fā)生某些行為(例如改變類的字段或?qū)傩裕蛘哌M行了某種形式的用戶交互操作)時,它可以讓對象通知調(diào)用程序??蛻艨梢园^事件處理程序的代碼來響應該事件。第7章將詳細介紹事件。3.2.2 函數(shù)成員函數(shù)成員提供了操作類中數(shù)據(jù)的某些功能,包括方法、屬性、構(gòu)造函數(shù)和終結(jié)器(finalizer)、運算符以及索引器。方法是與某個類相關(guān)的函數(shù),它們可以是實例方法,也可以是靜態(tài)方法。實例方法處理類的某個實例,靜態(tài)方法提供了更一般的功能,不需要實例化一個類(例如Console. WriteLine()方法)。下一節(jié)介紹方法。屬性是可以在客戶機上訪問的函數(shù)組,其訪問方式與訪問類的公共字段類似。C#為讀寫類上的屬性提供了專用語法,所以不必使用那些名稱中嵌有Get或Set的偷工減料的方法。因為屬性的這種語法不同于一般函數(shù)的語法,在客戶代碼中,虛擬的對象被當做實際的東西。構(gòu)造函數(shù)是在實例化對象時自動調(diào)用的函數(shù)。它們必須與所屬的類同名,且不能有返回類型。構(gòu)造函數(shù)用于初始化字段的值。終結(jié)器類似于構(gòu)造函數(shù),但是在CLR檢測到不再需要某個對象時調(diào)用。它們的名稱與類相同,但前面有一個符號。C+程序員應注意,終結(jié)器在C#中比在C+中用得少得多,因為CLR會自動進行垃圾收集,另外,不可能預測什么時候調(diào)用終結(jié)器。第12章將介紹終結(jié)器。運算符執(zhí)行的最簡單的操作就是+和-。在對兩個整數(shù)進行相加操作時,嚴格地說,就是對整數(shù)使用+運算符。C#還允許指定把已有的運算符應用于自己的類(運算符重載)。第6章將詳細論述運算符。索引器允許對象以數(shù)組或集合的方式進行索引。第6章介紹索引器。1. 方法在Visual Basic、C和C+中,可以定義與類完全不相關(guān)的全局函數(shù),但在C#中不能這樣做。在C#中,每個函數(shù)都必須與類或結(jié)構(gòu)相關(guān)。注意,正式的C#術(shù)語實際上區(qū)分了函數(shù)和方法。在這個術(shù)語中,函數(shù)成員不僅包含方法,而且也包含類或結(jié)構(gòu)的一些非數(shù)據(jù)成員,例如索引器、運算符、構(gòu)造函數(shù)和析構(gòu)函數(shù)等,甚至還有屬性。這些都不是數(shù)據(jù)成員,字段、常量和事件才是數(shù)據(jù)成員。(1) 方法的聲明在C#中,定義方法的語法與C風格的語言相同,與C+和Java中的語法也相同。與C+的主要語法區(qū)別是,在C#中,每個方法都單獨聲明為public或private,不能使用public:塊把幾個方法定義組合起來。另外,所有的C#方法都在類定義中聲明和定義。在C#中,不能像在C+中那樣把方法的實現(xiàn)代碼分隔開來。在C#中,方法的定義包括方法的修飾符(例如方法的可訪問性)、返回值的類型,然后是方法名、輸入?yún)?shù)的列表(用圓括號括起來)和方法體(用花括號括起來)。modifiers return_type MethodName(parameters)/ Method body每個參數(shù)都包括參數(shù)的類型名及在方法體中的引用名稱。但如果方法有返回值,return語句就必須與返回值一起使用,以指定出口點,例如:public bool IsSquare(Rectangle rect)return (rect.Height = rect.Width);這段代碼使用了一個表示矩形的.NET基類System.Drawing.Rectangle。如果方法沒有返回值,就把返回類型指定為void,因為不能省略返回類型。如果方法不帶參數(shù),仍需要在方法名的后面寫上一對空的圓括號()(就像本章前面的Main()方法)。此時return語句就是可選的- 當?shù)竭_右花括號時,方法會自動返回。注意方法可以包含任意多個return語句:public bool IsPositive(int value)if (value 20)/ code here to take error recovery action / (eg. throw an exception)elseforeName = value;注意這里的命名模式。我們采用C#的區(qū)分大小寫模式,使用相同的名稱,但公共屬性采用Pascal大小寫命名規(guī)則,而私有屬性采用camel大小寫命名規(guī)則。一些開發(fā)人員喜歡使用前面有下劃線的字段名_foreName,這會為識別字段提供極大的便利。Visual Basic 6程序員應注意,C#不區(qū)分Visual Basic 6中的Set和Let,在C#中,寫入訪問器總是用關(guān)鍵字set標識。(1) 只讀和只寫屬性在屬性定義中省略set訪問器,就可以創(chuàng)建只讀屬性。因此,把上面例子中的ForeName變成只讀屬性:private string foreName;public string ForeNamegetreturn foreName;同樣,在屬性定義中省略get訪問器,就可以創(chuàng)建只寫屬性。但是,這是不好的編程方式,因為這可能會使客戶機代碼的作者感到迷惑。一般情況下,如果要這么做,最好使用一個方法替代。(2) 屬性的訪問修飾符C#允許給屬性的get和set 訪問器設置不同的訪問修飾符,所以屬性可以有公共的get訪問器和私有或受保護的set訪問器。這有助于控制屬性的設置方式或時間。在下面的例子中,注意set訪問器有一個私有訪問修飾符,而get訪問器沒有任何訪問修飾符。這表示get訪問器具有屬性的訪問級別。在get 和 set 訪問器中,必須有一個具備屬性的訪問級別。如果get訪問器的訪問級別是protected,就會產(chǎn)生一個編譯錯誤,因為這會使兩個訪問器的訪問級別都不是屬性。public string Namegetreturn _name;set_name = value;(3) 自動實現(xiàn)的屬性如果屬性的set和get訪問器中沒有任何邏輯,就可以使用自動實現(xiàn)的屬性。這種屬性會自動實現(xiàn)基礎成員變量。上例的代碼如下:public string ForeName get; set;不需要聲明private string foreName。編譯器會自動創(chuàng)建它。使用自動實現(xiàn)的屬性,就不能在屬性設置中進行屬性的有效性驗證。所以在上面的例子中,不能檢查foreName是否少于20個字符。但必須有兩個訪問器。嘗試把該屬性設置為只讀屬性,就會出錯:public string ForeName get; 但是,每個訪問器的訪問級別可以不同。因此,下面的代碼是合法的:public string ForeName get; private set;(4) 內(nèi)聯(lián)一些開發(fā)人員可能會擔心,在上一節(jié)中,我們列舉了標準C#編碼方式導致了非常小的函數(shù)的許多情形,例如通過屬性訪問字段,而不是直接訪問字段。這些額外的函數(shù)調(diào)用是否會增加系統(tǒng)開銷,導致性能下降?其實,不需要擔心這種編程方式會在C#中帶來性能損失。C#代碼會編譯為IL,然后在運行期間進行正常的JIT編譯,獲得內(nèi)部可執(zhí)行代碼。JIT編譯器可生成高度優(yōu)化的代碼,并在適當?shù)臅r候內(nèi)聯(lián)代碼(即用內(nèi)聯(lián)代碼來替代函數(shù)調(diào)用)。如果某個方法或?qū)傩缘膱?zhí)行代碼僅是調(diào)用另一個方法,或返回一個字段,則該方法或?qū)傩钥隙ㄊ莾?nèi)聯(lián)的。但要注意,在何處內(nèi)聯(lián)代碼的決定完全由CLR做出。我們無法使用像C+中inline這樣的關(guān)鍵字來控制哪些方法是內(nèi)聯(lián)的。3. 構(gòu)造函數(shù)在C#中聲明基本構(gòu)造函數(shù)的語法與在Java 和C+中相同。下面聲明一個與包含的類同名的方法,但該方法沒有返回類型:public class MyClasspublic MyClass()/ rest of class definition與Java 和 C+相同,沒有必要給類提供構(gòu)造函數(shù),在我們的例子中沒有提供這樣的構(gòu)造函數(shù)。一般情況下,如果沒有提供任何構(gòu)造函數(shù),編譯器會在后臺創(chuàng)建一個默認的構(gòu)造函數(shù)。這是一個非常基本的構(gòu)造函數(shù),它只能把所有的成員字段初始化為標準的默認值(例如,引用類型為空引用,數(shù)字數(shù)據(jù)類型為0,bool為false)。這通常就足夠了,否則就需要編寫自己的構(gòu)造函數(shù)。注意:對于C+程序員來說,C#中的基本字段在默認情況下初始化為0,而C+中的基本字段不進行初始化,不需要像C+那樣頻繁地在C#中編寫構(gòu)造函數(shù)。構(gòu)造函數(shù)的重載遵循與其他方法相同的規(guī)則。換言之,可以為構(gòu)造函數(shù)提供任意多的重載,只要它們的簽名有明顯的區(qū)別即可: public MyClass() / zero-parameter constructor/ construction code public MyClass(int number) / another overload/ construction code 但注意,如果提供了帶參數(shù)的構(gòu)造函數(shù),編譯器就不會自動提供默認的構(gòu)造函數(shù),只有在沒有定義任何構(gòu)造函數(shù)時,編譯器才會自動提供默認的構(gòu)造函數(shù)。在下面的例子中,因為定義了一個帶單個參數(shù)的構(gòu)造函數(shù),所以編譯器會假定這是可以使用的唯一構(gòu)造函數(shù),不會隱式地提供其他構(gòu)造函數(shù):public class MyNumberprivate int number;public MyNumber(int number) this.number = number; 上面的代碼還說明,一般使用this關(guān)鍵字區(qū)分成員字段和同名的參數(shù)。如果試圖使用無參數(shù)的構(gòu)造函數(shù)實例化MyNumber對象,就會得到一個編譯錯誤:MyNumber numb = new MyNumber(); / causes compilation error注意,可以把構(gòu)造函數(shù)定義為private或protected,這樣不相關(guān)的類就不能訪問它們:public class MyNumberprivate int number;private MyNumber(int number) / another overloadthis.number = number; 在這個例子中,我們并沒有為MyNumber定義任何公共或受保護的構(gòu)造函數(shù)。這就使MyNumber不能使用new運算符在外部代碼中實例化(但可以在MyNumber上編寫一個公共靜態(tài)屬性或方法,以進行實例化)。這在下面兩種情況下是有用的:類僅用作某些靜態(tài)成員或?qū)傩缘娜萜?,因此永遠不會實例化希望類僅通過調(diào)用某個靜態(tài)成員函數(shù)來實例化(這就是所謂對象實例化的類代理方法)(1) 靜態(tài)構(gòu)造函數(shù)C#的一個新特征是也可以給類編寫無參數(shù)的靜態(tài)構(gòu)造函數(shù)。這種構(gòu)造函數(shù)只執(zhí)行一次,而前面的構(gòu)造函數(shù)是實例構(gòu)造函數(shù),只要創(chuàng)建類的對象,它都會執(zhí)行。靜態(tài)構(gòu)造函數(shù)在C+和Visual Basic 6中沒有對應的函數(shù)。class MyClassstatic MyClass()/ initialization code/ rest of class definition編寫靜態(tài)構(gòu)造函數(shù)的一個原因是,類有一些靜態(tài)字段或?qū)傩裕枰诘谝淮问褂妙愔?,從外部源中初始化這些靜態(tài)字段和屬性。.NET運行庫沒有確保靜態(tài)構(gòu)造函數(shù)什么時候執(zhí)行,所以不要把要求在某個特定時刻(例如,加載程序集時)執(zhí)行的代碼放在靜態(tài)構(gòu)造函數(shù)中。也不能預計不同類的靜態(tài)構(gòu)造函數(shù)按照什么順序執(zhí)行。但是,可以確保靜態(tài)構(gòu)造函數(shù)至多運行一次,即在代碼引用類之前執(zhí)行。在C#中,靜態(tài)構(gòu)造函數(shù)通常在第一次調(diào)用類的成員之前執(zhí)行。注意,靜態(tài)構(gòu)造函數(shù)沒有訪問修飾符,其他C#代碼從來不調(diào)用它,但在加載類時,總是由.NET運行庫調(diào)用它,所以像public和private這樣的訪問修飾符就沒有意義了。同樣,靜態(tài)構(gòu)造函數(shù)不能帶任何參數(shù),一個類也只能有一個靜態(tài)構(gòu)造函數(shù)。很顯然,靜態(tài)構(gòu)造函數(shù)只能訪問類的靜態(tài)成員,不能訪問實例成員。注意,無參數(shù)的實例構(gòu)造函數(shù)可以在類中與靜態(tài)構(gòu)造函數(shù)安全共存。盡管參數(shù)列表是相同的,但這并不矛盾,因為靜態(tài)構(gòu)造函數(shù)是在加載類時執(zhí)行,而實例構(gòu)造函數(shù)是在創(chuàng)建實例時執(zhí)行,所以構(gòu)造函數(shù)的執(zhí)行不會有沖突。如果多個類都有靜態(tài)構(gòu)造函數(shù),先執(zhí)行哪個靜態(tài)構(gòu)造函數(shù)是不確定的。此時靜態(tài)構(gòu)造函數(shù)中的代碼不應依賴其他靜態(tài)構(gòu)造函數(shù)的執(zhí)行情況。另一方面,如果靜態(tài)字段有默認值,它們就在調(diào)用靜態(tài)構(gòu)造函數(shù)之前指定。下面用一個例子來說明靜態(tài)構(gòu)造函數(shù)的用法,該例子基于包含用戶設置的程序(用戶設置假定存儲在某個配置文件中)。為了簡單一些,假定只有一個用戶設置- BackColor,表示要在應用程序中使用的背景色。因為這里不想編寫從外部數(shù)據(jù)源中讀取數(shù)據(jù)的代碼,所以假定該設置在工作日的背景色是紅色,在周末的背景色是綠色。程序僅在控制臺窗口中顯示設置- 但這足以說明靜態(tài)構(gòu)造函數(shù)是如何工作的。namespace Wrox.ProCSharp.StaticConstructorSamplepublic class UserPreferencespublic static readonly Color BackColor; static UserPreferences()DateTime now = DateTime.Now;if (now.DayOfWeek = DayOfWeek.Saturday | now.DayOfWeek = DayOfWeek.Sunday)BackColor = Color.Green;elseBackColor = Color.Red; private UserPreferences()這段代碼說明了顏色設置如何存儲在靜態(tài)變量中,該靜態(tài)變量在靜態(tài)構(gòu)造函數(shù)中進行初始化。把這個字段聲明為只讀類型,表示其值只能在構(gòu)造函數(shù)中設置。本章后面將詳細介紹只讀字段。這段代碼使用了Microsoft在Framework類庫中支持的兩個有用的結(jié)構(gòu)System.DateTime和System.Drawing.Color。DateTime結(jié)構(gòu)實現(xiàn)了靜態(tài)屬性Now和實例屬性DayOfWeek,Now屬性返回當前的時間,DayOfWeek屬性可以計算出某個日期是星期幾。Color(詳見第33章)用于存儲顏色,它實現(xiàn)了各種靜態(tài)屬性,例如本例使用的Red和Green,返回常用的顏色。為了使用Color結(jié)構(gòu),需要在編譯時引用System.Drawing.dll程序集,且必須為System.Drawing命名空間添加一個using語句:using System; using System.Drawing;用下面的代碼測試靜態(tài)構(gòu)造函數(shù): class MainEntryPointstatic void Main(string args)Console.WriteLine(User-preferences: BackColor is: + UserPreferences.BackColor.ToString();編譯并運行這段代碼,會得到如下結(jié)果:StaticConstructor.exeUser-preferences: BackColor is: Color Red當然,如果在周末執(zhí)行代碼,顏色設置就是Green。(2) 從其他構(gòu)造函數(shù)中調(diào)用構(gòu)造函數(shù)有時,在一個類中有幾個構(gòu)造函數(shù),以容納某些可選參數(shù),這些構(gòu)造函數(shù)都包含一些共同的代碼。例如,下面的情況:class Carprivate string description;private uint nWheels;public Car(string model, uint nWheels)this.description = description;this.nWheels = nWheels;public Car(string description)this.description = description;this.nWheels = 4;/ etc. 這兩個構(gòu)造函數(shù)初始化了相同的字段,顯然,最好把所有的代碼放在一個地方。C#有一個特殊的語法,稱為構(gòu)造函數(shù)初始化器,可以實現(xiàn)此目的:class Carprivate string description;private uint nWheels; public Car(string description, uint nWheels)this.description = description;this.nWheels = nWheels; public Car(string description) : this(model, 4)/ etc 這里,this關(guān)鍵字僅調(diào)用參數(shù)最匹配的那個構(gòu)造函數(shù)。注意,構(gòu)造函數(shù)初始化器在構(gòu)造函數(shù)之前執(zhí)行。現(xiàn)在假定運行下面的代碼:Car myCar = new Car(Proton Persona);在本例中,在帶一個參數(shù)的構(gòu)造函數(shù)執(zhí)行之前,先執(zhí)行帶2個參數(shù)的構(gòu)造函數(shù)(但在本例中,因為帶一個參數(shù)的構(gòu)造函數(shù)沒有代碼,所以沒有區(qū)別)。C#構(gòu)造函數(shù)初始化符可以包含對同一個類的另一個構(gòu)造函數(shù)的調(diào)用(使用前面介紹的語法),也可以包含對直接基類的構(gòu)造函數(shù)的調(diào)用(使用相同的語法,但應使用base關(guān)鍵字代替this)。初始化符中不能有多個調(diào)用。在C#中,構(gòu)造函數(shù)初始化符的語法類似于C+中的構(gòu)造函數(shù)初始化列表,但C+開發(fā)人員要注意,除了語法類似之外,C#初始化符所包含的代碼遵循完全不同的規(guī)則。可以使用C+初始化列表指定成員變量的初始值,或調(diào)用基類構(gòu)造函數(shù),而C#初始化符中的代碼只能調(diào)用另一個構(gòu)造函數(shù)。這就要求C#類在構(gòu)造時遵循嚴格的順序,但C+就沒有這個要求。這個問題詳見第4章,那時就會看到,C#強制遵循的順序只不過是良好的編程習慣而已。3.2.3 只讀字段常量的概念就是一個包含不能修改的值的變量,常量是C#與大多數(shù)編程語言共有的。但是,常量不必滿足所有的要求。有時可能需要一些變量,其值不應改變,但在運行之前其值是未知的。C#為這種情形提供了另一個類型的變量:只讀字段。readonly關(guān)鍵字比const靈活得多,允許把一個字段設置為常量,但可以執(zhí)行一些運算,以確定它的初始值。其規(guī)則是可以在構(gòu)造函數(shù)中給只讀字段賦值,但不能在其他地方賦值。只讀字段還可以是一個實例字段,而不是靜態(tài)字段,類的每個實例可以有不同的值。與const字段不同,如果要把只讀字段設置為靜態(tài),就必須顯式聲明。如果有一個編輯文檔的MDI程序,因為要注冊,需要限制可以同時打開的文檔數(shù)?,F(xiàn)在假定要銷售該軟件的不同版本,而且顧客可以升級他們的版本,以便同時打開更多的文檔。顯然,不能在源代碼中對最大文檔數(shù)進行硬編碼,而是需要一個字段表示這個最大文檔數(shù)。這個字段必須是只讀的-每次安裝程序時,從注冊表鍵或其他文件存儲中讀取。代碼如下所示: public class DocumentEditorpublic static readonly uint MaxDocuments; static DocumentEditor()MaxDocuments = DosomethingToFindOutMaxNumber();在本例中,字段是靜態(tài)的,因為每次運行程序的實例時,只需存儲最大文檔數(shù)一次。這就是在靜態(tài)構(gòu)造函數(shù)中初始化它的原因。如果只讀字段是一個實例字段,就要在實例構(gòu)造函數(shù)中初始化它。例如,假定編輯的每個文檔都有一個創(chuàng)建日期,但不允許用戶修改它(因為這會覆蓋過去的日期)。注意,該字段也是公共的,我們不需要把只讀字段設置為私有,因為按照定義,它們不能在外部修改(這個規(guī)則也適用于常量)。如前所述,日期用基類System.DateTime表示。下面的代碼使用帶有3個參數(shù)(年份、月份和月份中的日)的System.DateTime構(gòu)造函數(shù),可以從MSDN文檔中找到這個構(gòu)造函數(shù)和其他DateTime構(gòu)造函數(shù)的更多信息。 public class Documentpublic readonly DateTime CreationDate; public Document()/ Read in creation date from file. Assume result is 1 Jan 2002/ but in general this can be different for different instances/ of the class CreationDate = new DateTime(2002, 1, 1);在上面的代碼中,CreationDate和MaxDocuments的處理方式與其他字段相同,但因為它們是只讀的,所以不能在構(gòu)造函數(shù)外部賦值:void SomeMethod()MaxDocuments = 10;/ compilation error here. MaxDocuments is readonly還要注意,在構(gòu)造函數(shù)中不必給只讀字段賦值,如果沒有賦值,它的值就是其數(shù)據(jù)類型的默認值,或者在聲明時給它初始化的值。這適用于靜態(tài)和實例只讀字段。3.3 匿名類型第2章討論了var關(guān)鍵字,用于表示隱式類型化的變量。var與new關(guān)鍵字一起使用時,可以創(chuàng)建匿名類型。匿名類型只是一個繼承了Object的、沒有名稱的類。該類的定義從初始化器中推斷,類似于隱式類型化的變量。如果需要一個對象包含某個人的姓氏、中間名和名字,則聲明如下:var captain = new FirstName = James, MiddleName = T, LastName = Kirk;這會生成一個包含F(xiàn)irstName、MiddleName和LastName屬性的對象。如果創(chuàng)建另一個對象,如下所示:var doctor = new FirstName = Leonard, MiddleName = , LastName = McCoy;Captain和doctor的類型就是相同的。例如,可以設置captain = doctor。如果所設置的值來自于另一個對象,初始化器就可以簡化。如果已經(jīng)有一個包含F(xiàn)irstName、MiddleName和LastName屬性的類,且有一個該類的實例person,captain對象就可以初始化為:var captain = new (person.FirstName, person.MidleName, person.LastName);person對象的屬性名應投射為新對象名captain。所以captain對象應有FirstName、MiddleName和LastName屬性。這些新對象的類型名是未知的。編譯器為類型偽造了一個名稱,但只有編譯器才能使用它。我們不能也不應使用新對象上的任何類型引用,因為這不會得到一致的結(jié)果。3.4 結(jié)構(gòu)前面介紹了類如何封裝程序中的對象,也介紹了如何將它們保存在堆中,通過這種方式可以在數(shù)據(jù)的生存期上獲得很大的靈活性,但性能會有一定的損失。因托管堆的優(yōu)化,這種性能損失比較小。但是,有時僅需要一個小的數(shù)據(jù)結(jié)構(gòu)。此時,類提供的功能多于我們需要的功能,由于性能的原因,最好使用結(jié)構(gòu)??纯聪旅娴睦樱篶lass Dimensionspublic double Length;public double Width;上面的示例代碼定義了類Dimensions,它只存儲了一個項的長度和寬度。假定編寫一個安排設備的程序,讓人們試著在計算機上重新安排設備,并存儲每個設備項的維數(shù)。使字段變?yōu)楣沧侄?,就會違背編程規(guī)則,但我們實際上并不需要類的全部功能?,F(xiàn)在只有兩個數(shù)字,把它們當作一對來處理,要比單個處理方便一些。既不需要很多方法,也不需要從類中繼承,也不希望.NET運行庫在堆中遇到麻煩和性能問題,只需存儲
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年保健按摩師(按摩保健操練習)職業(yè)技能鑒定試卷
- 2025年評茶員(二級)茶葉投資分析與風險評估考試試卷
- 2025年電子商務師(中級)考試試卷:電商數(shù)據(jù)分析方法與應用試題解析
- 2025年德語TestDaF閱讀真題試卷(德語考試)攻略
- 2025年小學英語畢業(yè)考試模擬卷(英語綜合實踐口語與寫作)
- 2025年電子商務師(高級)考試試卷:電商數(shù)據(jù)分析與用戶畫像
- 軟件業(yè)軟件開發(fā)流程優(yōu)化與管理方法研究
- 農(nóng)村合作社與農(nóng)戶土地使用權(quán)流轉(zhuǎn)協(xié)議
- 線上直播帶貨平臺合作協(xié)議
- 2025年大學英語四級考試模擬試卷:翻譯能力提升與真題分析
- 房屋建筑與市政工程重大事故安全隱患判定標準解讀課件
- DB43-T 1267-2023 機動車檢驗機構(gòu)建設和運行管理規(guī)范
- 公司稅務注銷協(xié)議書
- 2025年人力資源管理專業(yè)期末考試卷及答案
- 防溺水安全家長會課件
- 第四單元:促銷問題(方案選擇問題)專項練習(學生版+解析)-2024-2025學年六年級數(shù)學上冊培優(yōu)精練(北師大版)
- 放射科實習生入科教育
- 國家開放大學國開電大《幼兒園課程基礎》形考任務1~4答案
- 2025至2030中國翡翠市場經(jīng)營績效與投資狀況研究報告
- 神經(jīng)可塑性在教育中的應用探索-全面剖析
- 2025年安全生產(chǎn)月主題培訓課件
評論
0/150
提交評論