展現(xiàn)C#教學(xué)課件_第1頁
展現(xiàn)C#教學(xué)課件_第2頁
展現(xiàn)C#教學(xué)課件_第3頁
展現(xiàn)C#教學(xué)課件_第4頁
展現(xiàn)C#教學(xué)課件_第5頁
已閱讀5頁,還剩55頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

展現(xiàn)c#

rainbow譯

第一章C#簡介

歡迎您加入C#的世界!這一章將把您引進(jìn)C#的天地,并回答一些相關(guān)的問題,如:您為什么要使用C#,

C++和C#的主要有什么不同點(diǎn),以及為什么C#使開發(fā)更容易而且還使您感到很有趣。

為什么是另外種編程語言?

必須回答的?個問題:當(dāng)您已經(jīng)使用C++或VB從事企業(yè)開發(fā)時,為什么還要學(xué)習(xí)另種語言?市場式的回

答就是:"在企業(yè)計(jì)算領(lǐng)域,C#將會變成為用于編寫“下?代窗口服務(wù)”(NextGenerationWindowsServices,

簡寫為NGWS)應(yīng)用程序的主要語言。這一章將對用參數(shù)請求提供支持,并陳列了C#的一些功能。這一章會使

您開胃的。

C#語言自C/C++演變而來。但是,它現(xiàn)代、簡單、完全面向?qū)ο蠛皖愋桶踩?。如果您是C/C++程序員,學(xué)

習(xí)曲線將會很平坦。許多C#語句直接借用您所喜愛的語言,包括表達(dá)式和操作符。假如不仔細(xì)看,簡直會把它

當(dāng)成C++。

關(guān)于C#最重要的一點(diǎn):它是現(xiàn)代的編程語言。它簡化和現(xiàn)代化了C++在類、名字空間、方法重載和異常處

理等領(lǐng)域。摒棄了C++的復(fù)雜性,使它更易用、更少出錯。

對C#的易用有貢獻(xiàn)的是減少了C++的?些特性,不再有宏、模板和多重繼承。特別對企業(yè)開發(fā)者來說,上

述功能只會產(chǎn)生更多的麻煩而不是效益。

使編程更方便的新功能是嚴(yán)格的類型安全、版本控制、垃圾收集(garbagecollect)等等。所有的這些功

能的目標(biāo)都是瞄準(zhǔn)了開發(fā)面向組件的軟件。

在繼續(xù)呈現(xiàn)出更多的功能之前,我想停下來并在下面說明C#至關(guān)重要的各種要素。

簡單

現(xiàn)代

面向?qū)ο?/p>

類型

版本

兼容

靈活

簡單

C#具有C++所沒有的一個優(yōu)勢就是學(xué)習(xí)簡單。該語言首要的目標(biāo)就是簡單。很多功能(還不如說是缺少了

C++的一些功能)有助于C#全方位的簡單。

在c#中,沒有c++C流行的指針。默認(rèn)地,您工作在受管理的代碼中,在那里不允許如直接存取內(nèi)存等

不安全的操作。我想沒有C++程序員可以聲稱,從沒有使用指針訪問過不屬了他們的內(nèi)存。

與指針”戲劇性”密切相關(guān)的是“愚蠢的”操作。在C++中,有和->操作符,它們用于名字空間、成員

和引用。對于新手來說,操作符至今仍是學(xué)習(xí)的道難關(guān)。C#棄用其它操作符,僅使用單個操作符"."o現(xiàn)在

個程序員所需要理解的就是嵌套名字的注解了。

您不必記住基于不同處理器架構(gòu)的隱含的類型,甚至各種整型的變化范圍。C#使用統(tǒng)一的類型系統(tǒng),摒棄

TC++多變的類型系統(tǒng)。這種系統(tǒng)充許您把各種類型作為一個對象查看,它是一個原始類型還是一個full-blown

類。和其它編程語言相比,由于加框(boxing)和消框(unboxing)的機(jī)制,把簡單類型當(dāng)作對象處理并不能獲得性

能的改善。稍后將詳細(xì)解釋加框和消框,但基本上僅當(dāng)需要時才使用對象訪問簡單類型這種技術(shù)。

首先,老練的程序員可能不喜歡它,但是整型和布爾型如今終歸是兩種完全不同的數(shù)據(jù)類型。這就意味著

原來if語句中錯誤的賦值現(xiàn)在會被編譯出錯,因?yàn)閕f語句只接受布爾類型的值。再也不會出現(xiàn)誤用賦值符為比

較符這樣的錯誤!

C#同時也解決了存在于C++中已經(jīng)有些年頭的多余東西(redundancies)。這種多余包括常數(shù)預(yù)定義,不同

字符類型等。鑒于多余表單已經(jīng)從該語言中消失,故一般在C#中都可以使用簡單了。

現(xiàn)代

您投入學(xué)習(xí)C#的努力是一筆大投資,因?yàn)镃#是為編寫NGWS應(yīng)用程序的主要語言而設(shè)計(jì)。您將會發(fā)現(xiàn)很多

自己用C++可以實(shí)現(xiàn)或苴很費(fèi)力實(shí)現(xiàn)的功能,在C#中不過是一部分基本的功能而已。

對于企業(yè)級的編程語言來說,新增的金融數(shù)據(jù)類型很受歡迎。您用到了一種新的十進(jìn)制數(shù)據(jù)類型,它專用

于金融計(jì)算方面。如果不喜歡這種現(xiàn)成簡單的類型,根據(jù)您應(yīng)用程序的特殊需求,可以很容易地創(chuàng)建出新的一

種數(shù)據(jù)類型。

我已經(jīng)提到,指針不再是您編程武器的一部分。不要太驚訝,全面的內(nèi)存管理已經(jīng)不是您的任務(wù)。運(yùn)行時

NGWS提供了一個垃圾收集器,負(fù)責(zé)C#程序中的內(nèi)存管理。因內(nèi)存和應(yīng)用程序都受到管理,所以很必要增強(qiáng)類

型安全,以確保應(yīng)用的穩(wěn)定性。

對于C++程序員,異常處理不是新的東西,但它是C#的主要功能。C#的異常處理與C++的不同點(diǎn)在于它是

交叉語言的(運(yùn)行時的另一個功能)。在沒有C#之前,您必須處理怪異的HRESULTs,但現(xiàn)在由于使用了基于異

常的健壯的出錯處理,這一切都結(jié)束了。

對于現(xiàn)代的應(yīng)用程序,安全是首要的,C#也不會例外。它提供了元數(shù)據(jù)語法,用于聲明下述NGWS安全模

式的能力和許可。元數(shù)據(jù)是NGWS運(yùn)行時的個關(guān)鍵的概念,下一章將涉及到它更深的含義。

面向?qū)ο?/p>

您不會預(yù)料一種新語言不支持面向?qū)ο蟮墓δ馨??C#當(dāng)然支持所有關(guān)鍵的面向?qū)ο蟮母拍?,如封裝、繼承

和多態(tài)性。完整的性類模式構(gòu)建在模式運(yùn)行時的虛擬對象系統(tǒng)(VOS,VirtualObjectSystem)的上層,VOS

將在下章描述。對象模式只是基礎(chǔ)的一部分,不再是編程語言的一部分。

您一開始必須關(guān)注的事,就是不再有全局函數(shù)、變量或者是常量。所有的東西都封裝在類中,包括事例成

員(通過類的事例一對象可以訪問)或都靜態(tài)成員(通過數(shù)據(jù)類型).這些使C#代碼更加易讀且有助于減少潛在的

命名沖突。

定義類中的方法默認(rèn)是非虛擬的(它們不能被派生類改寫)。主要論點(diǎn)是,這樣會消除由于偶爾改寫方法而

導(dǎo)致另外一些原碼出錯。要改寫方法,必須具有顯式的虛擬標(biāo)志。這種行為不但縮減了虛擬函數(shù)表,而且還

確保正確版本的控制。

使用C++編寫闋,您可以使用訪問權(quán)限(accessmodifiers)給類成員設(shè)置不同的訪問等級。C#同樣支持

private、protected和public三種訪問權(quán)限,而11還增加了第四種:inlerna三有關(guān)訪問權(quán)限的詳細(xì)情況

將在第五章"類"中說明。

您曾經(jīng)創(chuàng)建了多少個類是從多基類派生出來的(ATL程序員,您的投票不計(jì)在內(nèi)?。??大多數(shù)情況,僅需

從一個類派生出。多基類惹出的麻煩通常比它們解決的問題還多。那就是為什么C#僅允許一個基類。如果您覺

得需要多重繼承,可以運(yùn)用接口。

一個可能出現(xiàn)的問題:在C#中不存在指針,如何模仿它?這個問題的答案很有代表性,它提供了對NGWS

運(yùn)行時事件模式的支持。再次,我將把對它的全面解釋放到第五章。

類型安全

我再次選指針作為一個例子。在C++中擁有一個指針,您能自由地把它強(qiáng)制轉(zhuǎn)換成為任何類型,包括干出

諸如把一個int*(整型指針)強(qiáng)制轉(zhuǎn)換成一個double*(雙精度指針)這樣的傻事。只要內(nèi)存支持這種操作,它就"

干過”。這并不是您所想象的企業(yè)級編程語言的類型安全。

綱要性的問題,C#實(shí)施最嚴(yán)格的類型安全,以保護(hù)自己及垃圾收集器(garbagecollector)。

所以必須遵守C#中一些相關(guān)變量的規(guī)則:

不能使用沒有初始化的變量。對于對象的成員變量,編譯器負(fù)責(zé)清零。而局部變量,則由您負(fù)責(zé)清零。當(dāng)

您使用一個沒有初始化的變量時,編譯器會教您怎么做。優(yōu)點(diǎn)是能夠避免由于使用不經(jīng)初始化的變量計(jì)算結(jié)果

而導(dǎo)致的錯誤,而您還不知道這些奇怪的結(jié)果是如何產(chǎn)生的。

C#取消了不安全的類型轉(zhuǎn)換。不能把一個整型強(qiáng)制轉(zhuǎn)換成一個引用類型(如對象),而當(dāng)向下轉(zhuǎn)換時,C#驗(yàn)

證這種轉(zhuǎn)換是正確的。(也就是說,派生類真的是從向下轉(zhuǎn)換的那個類派生出來的。)

邊界檢查是C#的一部分。再也不會出現(xiàn)這種情況:當(dāng)數(shù)組實(shí)際只定義了n-1個元素,卻超額地使用了n個

元素。

算術(shù)運(yùn)算有可能溢出終值數(shù)據(jù)類型的范圍。C#允許在語句級或應(yīng)用程序級檢測這些運(yùn)算。在允許檢測溢出

的情況下,當(dāng)溢出發(fā)生時將會拋出一個異常。

在C#中,被傳遞的引用參數(shù)是類型安全的。

版本可控(Versionable)

在過去的幾年中,幾乎所有的程序員都至少有一次不得不涉及到眾所周知的"DLL地獄”。該問題起因于多

個應(yīng)用程序都安裝了相同DLL名字的不同版本。有時,老版本的應(yīng)用程序可以很好地和新版本的DLL一起工作,

但是更多的時候它們會中斷運(yùn)行.現(xiàn)在的版本問題真是令人頭痛。

就象您將在第八章”用C#寫組件”所看到的,NGWSruntime將對您所寫的應(yīng)用程序提供版本支持。C#可以

最好地支持版本控制。盡管C#不能確保正確的版本控制,但是它可以為程序員保證版本控制成為可能。有這種

支持,一個開發(fā)人員就可以確保當(dāng)他的類庫升級時,仍保留著對已存在的客戶應(yīng)用程序的二進(jìn)制兼容。

兼容

C#并沒有存在于一個封閉的世界中。它允許使用最先進(jìn)的NGWS的通用語言規(guī)定(CommonLanguage

Specification,簡寫為CLS)訪問不同的API。CLS規(guī)定了一個標(biāo)準(zhǔn),用于符合這種標(biāo)準(zhǔn)的語言的內(nèi)部之間的操

作。為了加強(qiáng)CLS的編譯,C#編譯器檢測所有的公共出口編譯,并在通不過時列出錯誤。

當(dāng)然,您也想能夠訪問舊一點(diǎn)的COM對象。NGWS運(yùn)行時提供對COM透明的訪問。如何集成原來的代碼將在

第10章〃非管理代碼的內(nèi)部操作”有介紹。

OLE自動化是一種特殊的動物。任一個使用C++創(chuàng)建OLE自動化項(xiàng)目的人已經(jīng)喜歡上各種各樣的自動化數(shù)

據(jù)類型。有個好消息就是C#支持它們,而沒有煩瑣的細(xì)節(jié)。

最后,C#允許您用C原型的API進(jìn)持內(nèi)部操作??梢詮哪膽?yīng)用程序訪問任何DLL中的入口點(diǎn)(有C的原

型)。用于訪問原始API的功能稱作平臺調(diào)用服務(wù)(PlaformInvocationServices,縮寫PInovke),第10章

將展示使用CAPI進(jìn)行內(nèi)部操作的一些例子。

靈活

上一部分的最后一段有可能提醒了程序員。您可能會問:”難道就沒有我要傳遞指針的API嗎?”您是正確

的。不是僅有少數(shù)的這種API,而是很多(有點(diǎn)保守的估計(jì))。這種對原始WIN32代碼的訪問有時導(dǎo)致對非安全

類指定指針的使用(盡管它們中的一些由于受COM和PInvoke的支持可以解決)。

盡管C#代碼的缺省狀態(tài)是類型安全的,但是您可以聲明一些類或者僅聲明類的方法是非安全類型的。這樣

的聲明允許您使用指針、結(jié)構(gòu),靜態(tài)地分配數(shù)組。安全碼和非安全碼都運(yùn)行在同?個管理空間,這樣暗示著當(dāng)

從安全碼調(diào)用非安全碼時不會陷入列集(marshaling)。

小結(jié)

C#語言從C和C++演變而來,它是給那些愿意犧牲C++?點(diǎn)底層功能,以獲得更方便和更產(chǎn)品化的企業(yè)開

發(fā)人員而創(chuàng)造的。C#現(xiàn)代、簡單、面向?qū)ο蠛皖愋桶踩?。盡管它借鑒了C和C++的許多東西,但是在一些諸如

名字空間、類、方法和異常處理等特定領(lǐng)域,它們之間還存在著巨大的差異。

C#為您提供了方便的功能,如垃圾收集、類型安全、版本控制,等等。僅有的"代價"就是,代碼操作默認(rèn)

是類型安全的,不允許指針。光是類型安全就可以搞定了。但是,如果您需要指針,仍可以通過非安全碼使用

它們,而且當(dāng)調(diào)用非安全碼時,不能含有列集。

*使用這本書你需要什么?

從這本書的觀點(diǎn)看,你所需要的就是下一代windows服務(wù)軟件開發(fā)包(NGWSSDK)。盡管至少只要有NGWS

Runtime和C#編譯器就可以,當(dāng)您探索這些激動人心的新技術(shù)功能時,在一臺機(jī)器上裝有說明文件檔和所有的

SDK工具(包括debugger),將是一個極好的主意。這本書不需要你裝在機(jī)器上的VisualStudio7的任何工具。

我僅建議你要有一個優(yōu)秀的支持行數(shù)的程序編輯器,用以編輯C#源文件。

第二章NGWSRuntime技術(shù)基礎(chǔ)

既然你已經(jīng)具有了C#全面的印象,我也想讓你了解NGWSruntime的全貌。C#依靠由NGWS提供的運(yùn)行時;

因此,有必要知道運(yùn)行時如何工作,以及它背后所蘊(yùn)含的概念。

所以,這一章分為兩部分一它們是所有的概念和使用的基礎(chǔ)。兩部分的內(nèi)容雖然有些重疊,但它有助于

加深理解正在學(xué)習(xí)的概念。

2.1NGWSRuntime

NGWS和NGWSRuntime為你提供了一種運(yùn)行時環(huán)境。該運(yùn)行時管理執(zhí)行代碼,并提供了使編程更容易的服

務(wù)。只要你的編譯器支持這種運(yùn)行時,你就會從這種受管理的執(zhí)行環(huán)境中得益。

你猜測C#編譯器支持NGWSruntime很正確,但是不僅它支持NGWSruntime,VB和C++也支持。這些為支

持運(yùn)行時所創(chuàng)建的代碼稱作"受管代碼”(managedcode),以下是你的應(yīng)用程序從NGWSruntime那里所得到的

利益:

交叉語言集成(通過通用語言規(guī)范)

自動內(nèi)存管理(垃圾收集)

交叉語言異常處理(統(tǒng)一展開)

增強(qiáng)安全(包括類型安全)

版本支持("DLL地獄”終結(jié)者)

組件交互簡化模式

因NGWSruntime要提供了所有的這些好處,編譯器必須把元文件和受管代碼?起發(fā)出。元文件描述代碼

中的類型,它和你的代碼存在起(與PE類似--PE為可變位執(zhí)行文件)

正如你從很多種交叉語言功能所看到的,NGWSruntime主要是關(guān)于高度集成交叉多異編程語言(tight

integrationacrossmultipledifferentprogramminglanguages),,這種支持可達(dá)到允許你從一個VB對象

派生出一個C#類的程度(我后面會給出要討論的文章).

C#程序員將會喜歡的一■個功能是,他們不必?fù)?dān)心內(nèi)存管理一也就是說不必?fù)?dān)心臭名昭著的內(nèi)存泄漏。NGWS

runtime提供了內(nèi)存管理,當(dāng)對象和變量的生命期結(jié)束(不再被引用)時,垃圾收集器糅放它們。我真的喜歡這

個功能,因?yàn)樵贑OM中的內(nèi)存管理一直是我的一塊心病。

應(yīng)該鼓勵配置一個管理應(yīng)用程序或者組件。因?yàn)楣芾響?yīng)用程序含有元數(shù)據(jù)文件,NGWSruntime可以利用這

些信息,以確保你的應(yīng)用程序具有它所需的各種規(guī)定版本。所產(chǎn)生的明顯效果為,由于你的代碼沒有相互之間

的依賴,很少可能出現(xiàn)中斷。

這章余下來的將分為兩部分,每一部分討論NGWSruntime的各個方面,直到你的C#應(yīng)用程序能執(zhí)行為止。

1,中間語言(IntermediateLanguage,縮寫IL)和元數(shù)據(jù)

2^即時編譯器(just-in-timecompliers,簡稱JITers)

2.1.1中間語言和元數(shù)據(jù)

由C#編譯器生成的受管代碼并不是原始代碼,但它是中間語言(IL)代碼。這種IL代碼自身變成了NGWS

runtime的受管執(zhí)行進(jìn)程的入口。1L代碼明顯的優(yōu)勢在于它是CPU無關(guān)的,這也意味著,你要用目標(biāo)機(jī)器上

的一個編譯器才能把1L代碼轉(zhuǎn)換成原始代碼。

盡管IL代碼由編譯器產(chǎn)生,但它并不是編譯器提供給運(yùn)行時僅有的東西。編譯器同樣產(chǎn)生有關(guān)你代碼

的元數(shù)據(jù),它告訴運(yùn)行

時有關(guān)你代碼的更多的東西,例如各種類型的定義、各種類型成員的簽名以及其它數(shù)據(jù)?;旧?,匠畫是類

型庫、注冊表內(nèi)容和其它用于COM的信息。盡管如此,元數(shù)據(jù)還是直接和執(zhí)行代碼合并在一起,并不處在隔離

的位置。

IL和元數(shù)據(jù)存放于擴(kuò)展了PE格式的文件中(PE格式用于.exe和.dll文件)。當(dāng)這樣的一個PE文件被裝載

時,運(yùn)行時從文件中定位和分離出元數(shù)據(jù)和IL。

在進(jìn)一步說明之前,我想給你已有的IL指令的簡短目錄。盡管它不是一個完整的清單,也不需要你熟記

和理解,但是它列出了你所必需的、C#程序所基于的知識基礎(chǔ)。

算術(shù)和邏輯操作符

控制流

直接內(nèi)存訪問

堆棧操作

參數(shù)和局部變量

堆棧分配

對象模式

實(shí)例類型值

臨界區(qū)

數(shù)組

分型位置

即時編譯器(JITters)

2.1.2即時編譯器(JITters)

由C#或其它能產(chǎn)生受管代碼的編譯器所生成的受管代碼就是IL碼。雖然IL代碼被包裝在一個有效的PE

文件中,但是你還是不能執(zhí)行它,除非它被轉(zhuǎn)換成為受管原始代碼。這就是NGWSruntime即時編譯器(也稱作

JITters)大顯身手的時候。

為什么你會對即時編譯代碼感到厭繁,為什么不把整個ILPE文件編譯成原始代碼?答案是時間一需要把

IL代碼編譯成CPU規(guī)格的代碼的時間。這種編譯將更加有效率,因?yàn)橐恍┏绦蚨螐膩砭蜎]有被執(zhí)行過。例如,

在我的字處理器中,郵件合并功能從來就沒有被編譯。

從技術(shù)上說,全部的處理過程如下:當(dāng)一個類型被裝載時,裝載器創(chuàng)建一個存根(stub),并使它連接每一

個類型的方法。當(dāng)個方法第詼被調(diào)用時,存根把控制交給JIT。JIT把IL編譯為原始代碼,且把存根指針

指向緩沖了的原始代碼。接著的調(diào)用將執(zhí)行原始碼。在某些位置上(Atsomepoint),所有的IL都被轉(zhuǎn)換成為

原始代碼,而JITter處于空閑狀態(tài)。

用的JIT編譯器。它是一個后臺(backend)優(yōu)化的編譯器,在前臺(upfront)實(shí)行數(shù)據(jù)流分析,并創(chuàng)建了高

度優(yōu)化的受管原始代碼作為輸出結(jié)果。JIT可以使用不嚴(yán)格的IL指令集編碼,但是所需資源將十分可觀。主要

的限制在于內(nèi)存足跡(footprint)、結(jié)果工作集,以及實(shí)行優(yōu)化所消耗的時間。

EconoJIT——和主JIT相比,EconJIT的目標(biāo)是把IL高速地轉(zhuǎn)換成受管原始代碼。它允許緩沖所產(chǎn)生的

原始代碼,但是輸出碼并不像JIT生成的代碼那樣優(yōu)化(代碼小)。當(dāng)內(nèi)存緊張時,快速代碼生成方案的優(yōu)勢將

蕩然無存。通過永久地拋棄無用的己JIT過的代碼,你可以把更大的IL程序裝入代碼緩沖區(qū)。因?yàn)镴IT編譯

快,執(zhí)行速度也仍然很快。

PreJIT—盡管它是基于主JIT的,但操作起來更象是個傳統(tǒng)的編譯器。你安裝了NGWS組件,它才能運(yùn)

行,才可以把此代碼編譯成受管原始代碼。當(dāng)然最終的結(jié)果為,更快的裝教時間和更快的應(yīng)用程序啟動時間(不

需要更多的JIT編譯)。

在所列出的JITters中,有兩個是運(yùn)行時的JITters??墒悄阍趺礇Q定要使用哪一個JIT,它如何使用內(nèi)

存?有一個稱作”JIT編譯管理器”的小應(yīng)用程序(jilman.exe),它存放于NGWSSDK安裝目錄下的bin目錄中。

當(dāng)執(zhí)行該程序時,它把?個圖標(biāo)加到系統(tǒng)任務(wù)條上,雙擊該圖標(biāo)打開程序?qū)υ捒?見圖2.1)。

圖2.1JIT編譯管理器允許你設(shè)置各種相關(guān)性能的選項(xiàng)

盡管它是個小小的對話框,可是你所選擇的選項(xiàng)功能是相當(dāng)強(qiáng)大的。每個選項(xiàng)將在以下描述。

UseEconoJITonly選項(xiàng)——當(dāng)該復(fù)選框沒有選上時,NGWSruntime使用默認(rèn)的正常的JIT編譯器。前面就曾

經(jīng)解釋過兩種JITter的區(qū)別。

MaxCodePitchOverhead%)選項(xiàng)——該設(shè)置僅保留給EconoJIT。它控制了J1T編譯時間和執(zhí)行代碼時間的百分

比。如果超過了設(shè)定的域值,代碼緩沖區(qū)得到擴(kuò)充,以縮短JIT編譯所消耗的時間。

LimitSizeofCodeCache選項(xiàng)一該項(xiàng)默認(rèn)為非選。沒有選擇該項(xiàng)意味著緩沖區(qū)將使用它所能得到的內(nèi)存。

如果你想限制緩沖區(qū)大小,復(fù)選該選項(xiàng),這將允許你使用MaxSizeofCache(byles)選項(xiàng)。

MaxSizeofCache(bytes)選項(xiàng)一控制容納JIT代碼的緩沖區(qū)的最大值。雖然你可以非常嚴(yán)格地限制這個值,

但你還是應(yīng)該小心,不能超過這個緩沖區(qū)所適合的最大值。否則該方法的JIT編譯將會失敗。

OptimizeForSize選項(xiàng)——告訴JIT編譯器,優(yōu)化的目的是為了使代碼更小而不是能執(zhí)行得更快。這個設(shè)置

默認(rèn)是關(guān)掉的。

EnableConcurrentGC[garbagecollection]選項(xiàng)垃圾收集(GC)默認(rèn)地運(yùn)行在用戶代碼的線程中。意味

GC發(fā)生時,可能會注意到回應(yīng)有輕微的延遲。為防止出現(xiàn)該現(xiàn)象,打開當(dāng)前GC。注意,當(dāng)前GC比標(biāo)準(zhǔn)GC更

慢,它僅在windows2000上寫時(thetimeofwriting)有效。

當(dāng)用C#創(chuàng)建項(xiàng)目時,你可能使用不同的設(shè)置試驗(yàn)過。當(dāng)創(chuàng)建"-intensive應(yīng)用程序時,你將會看到允許當(dāng)前

GC的最大差別。

2.2虛擬對象系統(tǒng)(VOS)

到目前為止,你僅看到了NGWSruntime如何工作,但是并不了解它工作的技術(shù)背景以及為什么它要這樣工作。

這節(jié)都是關(guān)于NGWS虛擬對象系統(tǒng)的(V0S)。

以卜.為在VOS中形成聲明、使用和管理類型模型時,NGWSruntime的規(guī)則。在V0S背后的思想是建立一個框架,

在執(zhí)行代碼時不能犧牲性能,允許交叉語言集成和類型安全。

我提到的框架是運(yùn)行時架構(gòu)的基礎(chǔ)。為了幫助你更好地了解它,我將它勾出四個區(qū)域。當(dāng)開發(fā)C#應(yīng)用程序和組

件時,理解它們很重要。

VOS類型系統(tǒng)一提供豐富的類型系統(tǒng),它打算支持全面編程語言的完全實(shí)施。

元數(shù)據(jù)一描述和引用VOS類型系統(tǒng)所定義的類型。元數(shù)據(jù)的永久格式與編程語言無關(guān),但是,元數(shù)據(jù)拿自己

當(dāng)作一種互換機(jī)制(nterchangemechanism)來使用,這種互換是在在工具和NGWS的虛擬執(zhí)行系統(tǒng)之間。

通用語言規(guī)范(CLS)-CLS定義了VOS中類型的子集,也定義了常規(guī)的用法。如果個類庫遵守CLS的規(guī)則,

它確保類庫可以在其它所有能實(shí)現(xiàn)CLS的編程語言上使用。

虛擬執(zhí)行系統(tǒng)(VES)—這是VOS實(shí)時的實(shí)現(xiàn)。VES負(fù)責(zé)裝入和執(zhí)行為NGWS運(yùn)得時編寫的程序。

這四個部分一起組成了NGWSruntime架構(gòu)。每一部分在下面小節(jié)中描述。

2.2.1VOS類型系統(tǒng)

VOS類型系統(tǒng)提供豐富的類型系統(tǒng),它打算支持多種編程語言的完全實(shí)施。所以,VOS必須都支持面向?qū)ο蟮?/p>

語言和過程編程語言。

現(xiàn)在,存在著很多種近似但有點(diǎn)不兼容的類型。就拿整型當(dāng)例子,在VB中,它是16位長,而在C++中,它是

32位。還有更多的例子,特別是用在日期和時間以及數(shù)據(jù)庫方面的數(shù)據(jù)類型。這種不兼容使應(yīng)用程序的創(chuàng)建和

維護(hù)不必要地復(fù)雜化,尤其當(dāng)程序使用了多種編程語言時。

另一個問題是,因?yàn)榫幊陶Z言之間存在著一些差別,你不能在一種語言中重用另一種語言創(chuàng)建的類型。(COM用

二進(jìn)制標(biāo)準(zhǔn)接口部分地解決了這個問題)o當(dāng)今代碼重用肯定是有限的。

發(fā)布應(yīng)用程序的最大障礙是各種編程語言的對象模型不統(tǒng)、兒乎每一方面都存在著差異:事件、屬性、永久

保存(persistence)等等。

VOS這里將改變這種現(xiàn)象。VOS定義了描述值的類型,并規(guī)定了類型的所有值所必須支持的一條合約。由于

前面提到的支持面向?qū)ο蠛瓦^程編程語言,就存在著兩種值和對象。

對于值,類型存儲于表述(representation)中,同樣操作也在其中實(shí)行。對象更強(qiáng)大因?yàn)樗@式地存于表述中。

每一個對象都有一個區(qū)別于其它對象的識別號。支持不同的VOS類型在第四章"C#類型"中提出。

2.2.2元數(shù)據(jù)

盡管元數(shù)據(jù)用于描述和引用由VOS類型系統(tǒng)定義的類型,但它還不能鎖定到這個單個口標(biāo)。當(dāng)你寫一個程序

時,通過利用類型聲明,你所聲明的類型(假定它們是數(shù)值類型或引用類型)被介紹給NGWSruntime類型系統(tǒng)。

類型聲明在存于PE可執(zhí)行文件內(nèi)部的元數(shù)據(jù)中得到描述。

基本匕元數(shù)據(jù)用了各項(xiàng)任務(wù):用于表示NGWSruntime用途的信息,如定位和裝載類、內(nèi)存中這些類的事例、

解決調(diào)用、翻譯IL為原始碼、加強(qiáng)安全并設(shè)置運(yùn)行時上下文邊界。

你不必關(guān)心元數(shù)據(jù)的生成。元數(shù)據(jù)是由C#的”代碼轉(zhuǎn)IL編譯器"(code-to-ILcompiler,不是JIT編譯器)生成的。

代碼轉(zhuǎn)IL編譯器發(fā)送二進(jìn)制元數(shù)據(jù)信息給PE文件,是以標(biāo)準(zhǔn)的方式發(fā)送的,不像C++編譯器那樣,為出口函

數(shù)創(chuàng)建它們自己的修飾名字。

你從元數(shù)據(jù)和可執(zhí)行代碼并存所獲得的主要優(yōu)勢為,有關(guān)類型的信息同類型自身固定在一起,不會遍布很多地

方"同樣有助于解決存在于COM中的版本問題。進(jìn)一步地,你可以在相同的上卜.文中使用不同的版本庫,因?yàn)?/p>

庫不僅被注冊表引用,也被包含在可執(zhí)行代碼中的元數(shù)據(jù)引用。

2.2.3通用語言規(guī)范

通用語言規(guī)范(CLS)并不是虛擬對象系統(tǒng)(VOS)真正的一部分,它是特殊的。CLS定義了VOS中的一個類型子集,

也定義了必須符合CLS的常規(guī)用法。

那么,對此有什么迷惑呢?如果一個類庫遵守CLS規(guī)則,其它編程語言同樣也遵守CLS規(guī)則,那么其它編程語

言的客戶也可以使用類庫。CLS是關(guān)于語言的交互可操作性(interoperability)。因此,常規(guī)用法必須僅遵循

外部可訪問項(xiàng)目(externallyvisibleitems)如方法、屬性和事件等等。

我所描述的優(yōu)點(diǎn)是你可以做以下工作。用C#寫個組件,在VB中派生它,因加在VB中的功能是如此之強(qiáng)大,

在C#中再次從VB類派生它。只要所有的外部可訪問項(xiàng)遵守CLS規(guī)則,這樣是可行的。

我在這本書中出示的代碼不關(guān)心CLS協(xié)定。但在構(gòu)建你的類庫時要注意到CLS協(xié)定。我提供了表2.1,用以給

類型和外部可訪問項(xiàng)定義協(xié)定規(guī)則。

這個清單不完整。它僅包含一些很重要的項(xiàng)目。我不指出出現(xiàn)在本書中每一種類型的CLS協(xié)定,所以有個好主

意:當(dāng)你尋找CLS協(xié)定時,至少應(yīng)該用瀏覽該表,以了解哪種功能有效。不要擔(dān)心你不熟悉這章表中的每一個

含義,在這本書中你會學(xué)到它們。

表2.1通能語言規(guī)范中的類型和功能

bool

char

byte

short

int

long

float

double

string

object(所有對象之母)

Arrays(數(shù)組)

數(shù)組的維數(shù)必須是已知的(>=1),而且最小下標(biāo)數(shù)必須為Oo

要素類型必須是一個CLS類型。

類型(Types)

可以被抽象或隱藏。

零或更多的接口可以被實(shí)現(xiàn)。不同的接口允許擁有具有相同名字和簽名的方法。

一個類型可以準(zhǔn)確地從一個類型派生。允許成員被覆蓋和被隱藏。

可以有零或更多的成員,它們是字段(fields)、方法、事件或者類型。

類型可以擁有零或更多個構(gòu)造函數(shù)。

?種類型的可訪問性可以是公共的或者對NGWS組件來說是局部的;但是,僅公共成員可以認(rèn)為是類型接口的

一部分。

所有的值型必須從系統(tǒng)值型繼承。異常是一個枚舉—它必須從系統(tǒng)枚舉(SystemEnum)繼承。

類型成員

類型成員允許隱藏或者覆蓋另一種類型中的其它成員。

參數(shù)和返回值的類型都必須是CLS協(xié)定類型。

構(gòu)造函數(shù)、方法和屬性可以被重載。

一個類型可以有抽象成員,但僅當(dāng)類型不被封裝時。

方法

一種方法可以是靜態(tài)、虛擬或者實(shí)例。

虛擬和實(shí)例方法可以是抽象的,或者是一個實(shí)現(xiàn)。靜態(tài)方法必須總擁有一個實(shí)現(xiàn)。

虛擬方法可能是最后的(或者不是)。

字段(Fields)

可以是靜態(tài)或者是非靜態(tài)。

靜態(tài)字段可以被描述或只初始化。

屬性

當(dāng)獲取和設(shè)置方法而不是使用屬性語法時,屬性可以公開。

獲取的返回類型和設(shè)置方法的第一個參數(shù)必須是相同的CLS類型一屬性的類型。

屬性名字必須不同,不同的屬性類型用于區(qū)分是不充分的。

由了使用方法實(shí)現(xiàn)屬性訪問,如果PropertyName是同一個類中定義的一個屬性,你不能實(shí)現(xiàn)命名為

get_PropertyName和set_PropertyName的方法。

屬性可以被索引。

屬性訪問必須遵循這種命名格式:getProName,setPropName<.

枚舉(Enumerations)

強(qiáng)調(diào)類型必須是byte、short,int或long。

每?個成員是?個枚舉類型的靜態(tài)描述字段。

一個枚舉不能實(shí)現(xiàn)任何接口。

你允許給多字段設(shè)定相同的值。

一個枚舉必須繼承系統(tǒng)枚舉(隱含在C#中)

異常

可以被引發(fā)和被捕獲。

門定義異常必須繼承系統(tǒng)異常。

接口

可需要實(shí)現(xiàn)其它接口。

一個接口可以定義屬性、事件和虛擬方法。實(shí)現(xiàn)取決于派生類。

事件

增加和取消方法必須是都提供或者都沒有,每一種方法采用一個參數(shù),它是一個從系統(tǒng)代表元(System

Delegate)派生下來的類。

自定義屬性

可以僅使用下更類型:Type(類型),char,char,bool,byte,short,int,long,float,double,enum(一

種CLS類型),andobject.

代表元(Delegates)

可以被創(chuàng)建和被激活

標(biāo)識符(Identifiers)

一個標(biāo)識符的第一個字母必須來自一限制集。

通過大小寫在單范圍內(nèi),不可能唯?地區(qū)別兩個或更多個標(biāo)識符(大小寫不敏感)。

2.2.4虛擬執(zhí)行系統(tǒng)(VES)

虛擬執(zhí)行系統(tǒng)實(shí)現(xiàn)了虛擬對象系統(tǒng)。通過實(shí)現(xiàn)一個負(fù)責(zé)NGWSruntime的執(zhí)行引擎(executionengine,蝌EE)

創(chuàng)建VES。這個執(zhí)行引擎執(zhí)行你用C#編寫和編譯的應(yīng)用程序。

下列組件為VES的一部分。

1、中間語言(IL)——被設(shè)計(jì)為很容易受各種各樣的編譯器所兼容。在該框架之外,C++、VB和C#編譯器都能

夠生成ILo

2、裝入受管代碼——這包括解決內(nèi)存中的名字、表層類(layingoutclasses),并且創(chuàng)建JIT編譯所必需

的存根。通過執(zhí)行經(jīng)常性校驗(yàn),包括加強(qiáng)?些訪問規(guī)則,類裝載器同樣也增強(qiáng)了安全性。

3、用JIT轉(zhuǎn)換IL成原始代碼——IL代碼并不是設(shè)計(jì)成為?種傳統(tǒng)的解釋字節(jié)代碼或樹型代碼,IL轉(zhuǎn)換是真

正的編譯。

4、裝入元數(shù)據(jù)、校驗(yàn)類型安全和方法的完整性

5、垃圾收集(GC)和異常處理——兩者都是基于堆棧格式的服務(wù)。受管代碼允許你動態(tài)地跟蹤堆棧。要動態(tài)地

識別各個堆??蚣?,JITter或其它編譯器必須提供一個代碼管理器。

6、描繪和查錯服務(wù)一兩者都取決于由源語言編譯器所生成的信息。必須發(fā)出兩個映射:一個映射從源語言

結(jié)構(gòu)發(fā)到指令流中的地址,一個映射從地址發(fā)到堆??蚣苤械奈恢?。當(dāng)執(zhí)行從IL到原始代碼的轉(zhuǎn)換時,這些

映射被重新計(jì)算。

7、管理線程和上下文,還有遠(yuǎn)程管理一VES為受管代碼提供這些服務(wù)。

雖然這個清單并不完整,但它足以讓你理解運(yùn)行時基于的由VES提供的低層架構(gòu)??隙▽袑iT討論運(yùn)行時

的書,而這本書將稍為深入地挖掘各種話題。

2.3小結(jié)

這?章,我?guī)愎淞?回運(yùn)行時的世界。我描述了當(dāng)創(chuàng)建、編譯和配置C#程序時它是如何工作的。你學(xué)會了

中間語言(IL),還有元數(shù)據(jù)是如何用于描述被編譯為IL的類型。元數(shù)據(jù)和IL都用于JITter檢測和執(zhí)行你的代

碼。你甚至可以選擇用哪一種JITter來執(zhí)行應(yīng)用程序。

在這一章的第:部分,涉及到了運(yùn)行時為何按這種方式工作的理論。你學(xué)了虛擬對象系統(tǒng)(VOS)和組成它的那

部分。對于類庫設(shè)計(jì)者最為感興趣的就是通用語言規(guī)范(CLS),它為基于VOS的語言交互操作設(shè)定規(guī)則。最后,

你看到了虛擬執(zhí)行系統(tǒng)(VES汝口何通過NGWSruntime實(shí)現(xiàn)VOS。

第三章第一個C#應(yīng)用程序

3.0選擇一個編輯器

盡管我是一個頑固的Notepad狂,但這次我不建議用它編輯源碼。原因是你正在與真正的編程語言打交道,使

用Notepad編輯源碼編譯時可能產(chǎn)生大量的錯誤信息行(C++程序員知道我在說什么。)

你有幾種選擇??梢灾匦屡渲媚阈湃蔚睦鲜絍isualC++6.0,使它能夠和C#源文件一起工作。第二種選擇是

使用新的VisualStudio7。第三,你可以用任何第三方程序編輯器,最好要支持行數(shù)、色彩編碼、工具集成

和良好的搜索功能。CodeWright就是其中個例子,如圖3.1所示。

圖3.1CodeWright是你可以用于創(chuàng)建C#代碼文件眾多可能編輯器中的一個。

當(dāng)然,在所提到的編輯器中,沒有一個對創(chuàng)建C#程序來說是必要的。用Notepad肯定可以編輯。但是,如果你

考慮到要編寫更大的項(xiàng)目,最好還是忍痛割愛吧。

3.1"Hell。World"代碼

討論編輯器有點(diǎn)離題,讓我們把話題轉(zhuǎn)回到一個非常出名的小應(yīng)用程序。這個最短的C#版本應(yīng)用程序見清單

3.Io把它存起來,文件名為helloworld.cs,以便使你能按照說明,完成諸如編譯應(yīng)用程序等其它余下來的

步驟。

清單3.1最簡單的"HelloWorld”程序

1:classHelloWorld

2:{

3:publicstaticvoidMainO

4:{

5:System.Console.WriteLine(^HelloWorld");

6:}

7:}

在C#中,代碼塊(語句組)由大括?。▄和})所括住。所以,甚至你以前沒有CH的經(jīng)驗(yàn),你也可以說出Main。方

法就是HelloWorld類語句的部分,因?yàn)轭惐焕ㄔ谒x的大括弧中。

C#應(yīng)用程序(可執(zhí)行)的入口點(diǎn)就是staticMain方法,它必須包含在?個類中。僅有一個類能使用該標(biāo)志定義,

除非你告訴編譯器它應(yīng)使用哪一個Main方法(否側(cè),會產(chǎn)生一個編譯錯誤)。

和C++相比,Main的第一個字母是大寫的M,而不是你曾經(jīng)使用過的小寫字母。在這個方法中,你的程序開

始并結(jié)束。方法中可以調(diào)用其它方法一如這個例子中,用于輸出文本一或者創(chuàng)建對象并激活該方法。

正如你所看到的,Main方法返回一個void類型。

publicstaticvoidMain()

盡管看到這些語句時,C++程序員肯定會覺得似曾相識,但是其他程序員并不如此。首先,國田的訪問標(biāo)志

告訴我們這個方法可以被任何程序訪問,這是它被調(diào)用的必要條件。其次,S意味著沒血先創(chuàng)辿類的實(shí)例

也可以調(diào)用方法一你所要做的就是用類名調(diào)用方法。

HelloWorld.Main();

但是,我不贊成在Main方法中執(zhí)行這行代碼,遞歸會導(dǎo)致堆棧溢出。

另一重要的方面是返回類型。對于方法Main,可選擇麗(意味存根本就沒仃返|"1值),或?yàn)閕nt為整型結(jié)果(應(yīng)

用程序返回的錯誤級別)。因此,兩種可能的Main方法為:

publicstaticvoidMain()

publicstaticintMainO

C++程序員會同樣知道后面我要提到的—可以傳給應(yīng)用程序的命令行參數(shù)數(shù)組。如:

pub1icstaticvoidMain(string口虹gs)

我現(xiàn)在并不想詳細(xì)地說明如何訪問參數(shù),但我想事先給C++程序員一個警告:和C++相比,應(yīng)用程序路徑不是

這個數(shù)組的一部分。僅僅那些參數(shù)包含在這個數(shù)組中。

在對Main方法并不簡短的介紹之后,讓我們把注意力集中到唯一真正的代碼行一這行代碼在屏幕上顯示

"HelloWold〃。

System.Console.WriteLine(/zHelloWorld");

假如不是由于有了System,大家會馬上猜到WriteLine是Console對象的一個靜態(tài)方法。那么|Syst畫代表什

么呢?它是包含Cons含e對象的名字空間(范圍),漏上并不是每次都在Console對象前加上名字空間的前綴,

你可以象清單3.2所示范的那庠,在應(yīng)用程序中引入名字空間,

清單3.2在應(yīng)用程序中引入名字空間

1:usingSystem;

2:

3:classHei1oWor1d

4:{

5:publicstaticvoidMain()

6:{

7:Console.WriteLine(z,HelloWorld");

8:}

9:}

所有你要做的就是給System名字空間加一個using指令。在這之后,不再需要規(guī)定名字空間,就可以使用它

們的方法和屬性了。NGWS框架體系中有很多的名字空間,我只對巨大的名字空間池中的少數(shù)幾個對象進(jìn)行探

討。但在第八章〃用C#寫組件〃將介紹為你的對象創(chuàng)建自己的名字空間。

3.2編譯應(yīng)用程序

由「NGWSRuntime支持所有的編譯器(YB、C++和C#),你不必買一個單獨(dú)的開發(fā)工具用來把應(yīng)用程序編譯成

IL(中間語言)。但是,如果你從沒有用過命令行編譯器編譯過應(yīng)用程序(僅懂得編譯名,而沒有熟記),它還

是你的首要選擇。

打開命令提示符并切換到存helloworld.cs的目錄。敲入以下命令:

eschcllowcrld.es

helloworld.es被編譯并鏈接成被11world,exe。因?yàn)樵创a沒有錯誤(那當(dāng)然!),C#編譯器沒有出錯提示,在

整個編譯過程沒有絲毫停頓。如圖3.2所示。

圖3.2使用命令行編譯器esc.exe編譯應(yīng)用程序

現(xiàn)在你已經(jīng)準(zhǔn)備好運(yùn)行第一個真正用C#編寫的應(yīng)用程序。簡單地在命令行上敲入helloworld,輸出結(jié)果為

"HelloWorld”。

在繼續(xù)往下介紹之前,我想稍為想象一下第一個應(yīng)用程序和一個編譯器開關(guān)的使用:

esc/out:hello,exehelloworld,cs

這個開關(guān)告訴編譯器輸出文件命名為hello.exe,雖然這不是什么絕招,但它是這本書中用到的未來編譯器的

基本功。

3.3輸入和輸出

到目前為止,我僅僅演示了把簡單的常量字符串輸出到屏幕。盡管這本書只介紹了C#編程的概念而不介紹用戶

接口編程,但我需要讓你迅速學(xué)會簡單的屏幕輸入和輸出方法—相應(yīng)于C的scanf和printf,或者C++的

cin和cout。我不能提供VB相應(yīng)的函數(shù),因?yàn)槠聊辉L問不是該核心語言的一部分。

你只需要能夠讀用戶的輸入并提示一些信息給用戶。清單3.3說明如何讀二個用戶請求的名字輸入,.并顯示二

條已定制好的“He11?!ㄐ畔?..

Listing3.3從控制臺讀輸入信息

1:usingSystem;

2:

3:classInputOutput

4:{

5:publicstaticvoidMainO

6:{

7:Console.Write(Z/Pleaseenteryourname:");

8:stringstrName:Console.ReadLineO;/*讀入信息*/

9:Console^^TT^IJneC^Hello〃+strName);量/*輸出信息*/

10:}

11:}

第7行使用Console對象的?個新方法用于提示文本信息給用戶,它就是Write方法。它(Write)與WriteIJne

不同的地方在于它輸出時不換行。我使用這種方法以便用戶可以在信息提示的同一行輸入幺字。

在用戶輸入他的名字后(并按回車鍵),|飛空螞吧J方法讀入了一個字符串變量。名字字符串連接到常量字符串

"Hello",并用我們早已熟悉的WriteLine方法顯示出來(見圖3.2)。

圖3.3編譯和運(yùn)行定制的Hell。應(yīng)用程序

你幾乎已學(xué)完了NGWS框架必要的輸入和輸出功能。但是,你還需要為用戶顯示多個值。為用戶寫一個格式串。

清單3.4展示個例子。

清單3.4使用不同的輸出方法

1:usingSystem;

2:

3:classInputOutput

4:{

5:publicstaticvoidMain()

6:{

7:Console.Write(Z/Pleaseenteryourname:");

8:stringstrName=Console.ReadLineO;

9:Console.WriteLine(""Hello{0},z,strName);

10:}

11:)

第9行包含了使用格式申的Console.WriteLine語句。格式申例子如H:

"Hello{0}"/*“0”為下標(biāo)*/

{。代替WriteLine方法的參數(shù)表中緊隨格式串后的第一個變量。你可以用該技術(shù)格式化超過三個變量。

Console.WriteLine(z,Hello{0}{1},from{2}”,

strFirstname,strLastname,strCity);

當(dāng)然,并不僅限于只使用字符串變量。你可以使用任何類型,這些類型在后面的第四章〃C#類型〃中有討論。

3.4添加注釋

當(dāng)寫代碼時,你應(yīng)為代碼寫注釋條文,解釋實(shí)現(xiàn)的內(nèi)容、變更史等。盡管你注釋中提供的信息(如果有的話)是

給你寫的,但是你還是必須遵守寫C#注釋的方法。清單3.5顯示采用的兩種不同的方式。

清單3.5給你的代碼添加注釋

1:usingSystem;

2:

3:classHelloWorld

4:{

5:publicstaticvoidMainO

6:{

7://這是單行注釋

8:/*這種注釋

9:跨越多行*/

10:Console.WriteLineloWorld"*/);

11:}

12:}

〃〃〃符號用于單行注釋。你可以用〃//”注釋當(dāng)前所在行,或是跟在?個代碼語句的后面:

intnMyVar=10;//胡說八道

所有在〃〃”后面的被認(rèn)為是一條注釋;所以,你可以同樣用它們來注釋一整行或一行源代碼的部分。這種注釋

方式同C++中介紹的相似。

如果你的注釋跨越多行,必須使用〃/**/〃的字符組合。這種方式在C中有效。除了單行注釋外,這種方式在

C++和C#中還同樣有效。因C/C++和C#都使用這種多行注釋方式,所以它們也使用相同的終結(jié)符。請看下列代

碼行:

/*Console.WriteLineC*HelloWorld");*/

我使用"/**/"簡單地注釋一整行?,F(xiàn)在我假定這一行是很長代碼的一部分,而且我決定要暫時禁用一個程序

塊:

/*

/*Console.WriteLine(,zHelloWorld*);*/

*/

這個結(jié)構(gòu)所存在的問題為:"Hell。World〃那?行后面的〃*/〃終止了始于第?行的〃/*〃的注釋,余下的代碼對

編譯器有效,你將看到?些有趣的出錯信息。至少最后的〃*/〃被標(biāo)志為歸屬錯誤。我只不過想提醒?下,讓

你了解這種借誤。

3.5小結(jié)

在這?章中,你創(chuàng)建、編譯并執(zhí)行了第?個C#應(yīng)用程序:著名的“HelloWorld”程序。我用這個短短的應(yīng)用程序

給你介紹有關(guān)Main方法,它是一個應(yīng)用程序的入口點(diǎn),也是出口點(diǎn)。這個方法可以沒有返回值或返回一個整

數(shù)錯誤級別。如果你的應(yīng)用程序用參數(shù)調(diào)用,你可以(但不必要)讀出并使用它們。

在編譯和測試應(yīng)用程序后,你學(xué)到了更多的由Console對象提供的有關(guān)輸入和輸出的方法。對于學(xué)習(xí)C#而言,

它們足以創(chuàng)建出有意義的控制臺例子,但用戶接口的大部分將是WFC、WinForms或者ASP+。

第四章C#類型

既然你知道了怎樣創(chuàng)建一個簡單的C#程序,我將會給你介紹C#的類型系統(tǒng)。在這一章中,你學(xué)到如何使

用不同的值和引用類型,加框和消框機(jī)制能為你作些什么。盡管這一章的不側(cè)重于例子,但你可以學(xué)到很多重

要的信息,關(guān)于如何創(chuàng)建現(xiàn)成類型的程序。

4.1值類型

各種值類型總是含有相應(yīng)該類型的一個值。C#迫使你初始化變量才能使用它們進(jìn)行計(jì)算-變量沒有初始化不會

出問題,因?yàn)楫?dāng)你企圖使用它們時,編譯器會告訴你。每當(dāng)把一個值賦給一個值類型時,該值實(shí)際上被拷貝

了。相比,對于引用類型,僅是引用被拷貝了,而實(shí)際的值仍然保留在相同的內(nèi)存位置,但現(xiàn)在有兩個對象指

向了它(引用它)。C#的值類型可以歸類如下:

,簡單類型(Simpletypes)

,結(jié)構(gòu)類型(structtypes)

,枚舉類型(Enumerationtypes)

4.1.1簡單類型

在C#中出現(xiàn)的簡單類型共享一些特性。第、它們都是.NET系統(tǒng)類型的別名。第二,由簡單類型組成的常量

表達(dá)式僅在編譯時而不是運(yùn)行時受檢測。最后,簡單類型可以按字面被初始化。以下為C#簡單類型歸類:

?整型

?布爾型

?字符型(整型的一種特殊情況)

?浮點(diǎn)型

?小數(shù)型

整型

C#41有9個整1項(xiàng)。TiTm'+byte、short、ushort、int、uint、long、ulong和char(單獨(dú)一節(jié)討論)。

它們具有以下特性:一

?sbyte型為有符號8位整數(shù),取值范圍在128、127之間。

?bytet型為無符號16位整數(shù),取值范圍在0~255之間。

?short型為有符號16位整數(shù),取值范圍在-32,768~32,767之間。

?ushort型為無符號16位整數(shù),取值范圍在0~65,535之間。

?int型為有符號32位整數(shù),取值范圍在-2,147,483,648、2,147,483,647之間。

?uint型為無符號32位整數(shù),取值范圍在0~4,294,967,295之間。

?long型為64位有符號整數(shù),取值范圍在9,223,372,036,854,775,808'9,223,372,036,854,775,807之間。

?ulong型為64位無符號整數(shù),取值范圍在0~18,446,744為73,709,551,615之間。

VB和C程序員都可能會對int和long數(shù)據(jù)類型所代表的新范圍感到驚訝。和其它的編程語言相比,在C#中,

int不再取決于一個機(jī)器的字(word)的大小,而long被設(shè)成64位。

布爾型

布爾數(shù)據(jù)類型有trilT'^ralse兩個布爾值。可以賦于true或false值給一個布爾變量,或可以賦于一個表達(dá)

式,其所求出的值等于兩者之一:

boolbTest=(80>90);

與C和C++相比,在C#中,true值不再為任何非零值。不要為了增加方便而把其它整型轉(zhuǎn)換成布爾型。

字符型

字符型為一個單Unicode字符。一個Unicode字符16位長,它可以用來表示世界上多種語言。可以按以下方

法給一個字符變量賦值:

charchSomeChar='A';

除此之外,可以通過十六進(jìn)制轉(zhuǎn)義符(前綴\x)或Unicode表示法給變量賦值(前綴\u):

charchSomeChar='\x0065);

charchSomeChar='\u0065);

不存在把char轉(zhuǎn)換成其它數(shù)據(jù)類型的隱式轉(zhuǎn)換。這就意味著,在C#中把一個字符變量當(dāng)作另外的整數(shù)數(shù)據(jù)類

型看待是行不通的—這是C程序員必須改變習(xí)慣的另一個方面。但是,可以運(yùn)用顯式轉(zhuǎn)換:

charchSomeChar=(char)65;

intnSomelnt=(int)'A';

在C中仍然存在著轉(zhuǎn)義符(字符含義)。要換換腦筋,請看表4.1。

Table4.1轉(zhuǎn)義符(EscapeSequences)

義符

?專

字符名

,

\引

\”

\\斜

\o字

\a嘆

(Alert)

退

\b格

\f頁

\行

n

\車

r

\t平

\直tab

Vtab

4.],1.4浮點(diǎn)型

兩種數(shù)據(jù)類,被當(dāng)疝嬴冽E*t和double。它們的差別在于取值范圍和精度:

float:取值范圍在1.5xl0"-45~3.4xl(T38之間,精度為7位數(shù)。

double:取值范圍在5.0x10-324~1.7xl0~308之間,精度為15~16位數(shù)。

當(dāng)用兩種浮點(diǎn)型執(zhí)行運(yùn)算時,可以產(chǎn)生以卜的值:

正零和負(fù)零

正無窮和負(fù)無窮

非數(shù)字值(Not-a-Number,縮寫NaN)

非零值的有限數(shù)集

另一個運(yùn)算規(guī)則為,當(dāng)表達(dá)式中的一個值是浮點(diǎn)型時,所有其它的類型都要被轉(zhuǎn)換成浮點(diǎn)型才能執(zhí)行運(yùn)算。

小數(shù)型(ThedecimalType)

小數(shù)型是一種高精度、128位數(shù)據(jù)類型,它打算用了金融和貨幣的計(jì)算。它所表示的范圍從大約L0xl0、28到

7.9x10^28,具有28至29位有效數(shù)字。要注意,精度是以位數(shù)(digits)而不是以小數(shù)位(decimalplaces)

表示。運(yùn)算準(zhǔn)確到28個小數(shù)位的最大值。

正如你所看到的,它的取值范圍比double的還窄,但它更精確。因此,沒有decimal和double之間的隱式轉(zhuǎn)

換一往一個方向轉(zhuǎn)換可能會溢出,往另外一個方向可能會丟失精度。你不得不運(yùn)用顯式轉(zhuǎn)換。

當(dāng)定義一個變量并賦值給它時,使用m后綴以表明它是一個小數(shù)型:

decimaldecMyValue=1.Om;

如果省略了m,在變量被減向之前,它將被編譯器認(rèn)作double型。

4.1.2結(jié)構(gòu)類型

一個結(jié)構(gòu)類型可以聲明構(gòu)造函數(shù)、常數(shù)、字段、方法、屬性、索引、操作符和嵌套類型。盡管列出來的功能看

起來象一個成熟的類,但在C#中,結(jié)構(gòu)和類的區(qū)別在了結(jié)構(gòu)是一個值類型,而類是一個引用類型。與C++相比,

這里可以用結(jié)構(gòu)關(guān)鍵字定義一個類。

使用結(jié)構(gòu)的主要思想是用于創(chuàng)建小型的對象,如Point和Fileinfo等等。你可以節(jié)省內(nèi)存,因?yàn)闆]有如類對

象所需的那樣有額外的引用產(chǎn)生。例如,當(dāng)聲明含有成千上萬個對象的數(shù)組時,這會引起極大的差異。

清單蟲1包含一個命名為IP的簡單結(jié)構(gòu),它表示一個使用byte類型的4個字段的IP地址。我不包括方法等,

因?yàn)檫@

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論