版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 馬術(shù)開業(yè)活動策劃方案(3篇)
- 景區(qū)游樂設(shè)施定期檢查制度
- 檔案管理制度
- 2026江西贛州市章貢區(qū)社區(qū)工作者(專職網(wǎng)格員)招聘102人備考題庫完整答案詳解
- 2026廣東佛山南海大瀝鎮(zhèn)海北第四幼兒園招聘備考題庫含答案詳解
- 2025福建福州市鼓樓區(qū)鼓東街道招聘專職網(wǎng)格員1人備考題庫(12月)含答案詳解
- 2026四川成都傳媒集團(tuán)集團(tuán)管理媒體單位副職招聘1人備考題庫及完整答案詳解
- 酒店裝修款財(cái)務(wù)制度
- 關(guān)于酒店前廳部財(cái)務(wù)制度
- 知乎夫妻財(cái)務(wù)制度
- 2026年鋰電池項(xiàng)目投資計(jì)劃書
- (二診)綿陽市2023級高三第二次診斷考試歷史試卷A卷(含答案)
- 2026年電力交易員崗位能力認(rèn)證考核題含答案
- 2026年及未來5年市場數(shù)據(jù)中國金剛石工具行業(yè)投資分析及發(fā)展戰(zhàn)略咨詢報(bào)告
- 2025-2026學(xué)年總務(wù)主任年度述職報(bào)告
- 機(jī)電井(水源井)工程施工技術(shù)方案
- 2025ACCP實(shí)踐指南:危重患者血漿與血小板輸注指南解讀
- 【語文】遼寧省沈陽市沈河區(qū)文化路小學(xué)小學(xué)一年級下冊期末試卷(含答案)
- 腳手架施工環(huán)境保護(hù)措施方案
- 符號互動理論課件
- 獸藥使用法律法規(guī)學(xué)習(xí)材料
評論
0/150
提交評論