| 導購 | 订阅 | 在线投稿
分享
 
 
 

C#學習筆記

2006-12-16 17:29:09  編輯來源:互聯網  简体版  手機版  移動版  評論  字體: ||

1, 結構(struct) 與 類(class)

[attributes] [modifiers] struct identifier [:interfaces] body [;]

結構與類很相似,都表示可以包含數據成員和函數成員的數據結構。與類不同的是,結構是值類型並且不需要堆分配。結構類型的變量直接包含結構的數據,而類類型的變量包含對數據的引用(該變量稱爲對象)。 struct 類型適合表示如點、矩形和顔色這樣的輕量對象。盡管可能將一個點表示爲類,但結構在某些方案中更有效。在一些情況下,結構的成本較低。例如,如果聲明一個含有 1000 個點對象的數組,則將爲引用每個對象分配附加的內存。結構可以聲明構造函數,但它們必須帶參數。聲明結構的默認(無參數)構造函數是錯誤的。總是提供默認構造函數以將結構成員初始化爲它們的默認值。在結構中初始化實例字段是錯誤的。在類中,必須初始化實例對象. 使用 new 運算符創建結構對象時,將創建該結構對象,並且調用適當的構造函數。與類不同的是,結構的實例化可以不使用 new 運算符。如果不使用 new,那麽在初始化所有字段之前,字段將保持未賦值狀態且對象不可用。對于結構,不像類那樣存在繼承。一個結構不能從另一個結構或類繼承,而且不能作爲一個類的基。但是,結構從基類 Object 繼承。結構可實現接口,其方式同類完全一樣。

[c++] 與 C++ 不同,無法使用 struct 關鍵字聲明類。在 C# 中,類與結構在語義上是不同的。結構是值類型,而類是引用類型。

2, 裝箱和拆箱(取消裝箱)

裝箱是值類型到 object 類型或到該值類型所實現的任何接口類型的隱式轉換。將一個值的值裝箱會分配一個對象實例並將該值複制到新的對象中。關鍵字 object. 取消裝箱是從 object 類型到值類型或從接口類型到實現該接口的值類型的顯式轉換。取消裝箱操作包括:檢查對象實例,確保它是給定值類型的一個裝箱值。將該值從實例複制到值類型變量中。

例:

int i = 123; // A value type

object box = i; // Boxing

int j = (int)box; // Unboxing

裝箱轉換

取消裝箱

3 , 隱式和顯式

下列轉換屬于隱式轉換:例:object o=i;

標識轉換。

隱式數值轉換。

隱式枚舉轉換。

隱式引用轉換。

裝箱轉換。

隱式常數表達式轉換。

用戶定義的隱式轉換。

下列轉換屬于顯式轉換: object 0=(object)i;

所有隱式轉換。

顯式數值轉換。

顯式枚舉轉換。

顯式引用轉換。

顯式接口轉換。

取消裝箱轉換。

用戶定義的顯式轉換

4, delegate(委托)

delegate void D(int x);

class C{

public static void M1(int i) { /* ... */ }

public static void M2(int i) { /* ... */ }}

class{…….D cd1 = new D(C.M1);………….}

委托是一個數據結構,該數據結構引用一個靜態方法,或引用一個對象實例和該對象的實例方法。在 C 或 C++ 中與委托最接近的是函數指針,但函數指針只能引用靜態函數,而委托可以同時引用靜態方法和實例方法。在後一種情況中,委托不僅存儲對方法入口點的引用,還存儲對調用其方法的對象的引用。與 C++ 函數指針不同,委托是完全面對對象的;與指向成員函數的 C++ 指針不同,委托同時封裝對象實例和方法。委托聲明定義從類 System.Delegate 派生的類。委托實例封裝一個或多個方法,每個方法都被稱爲可調用實體。對于實例方法,可調用實體由一個實例和該實例上的方法組成。對于靜態方法,可調用實體僅由一個方法組成。給定委托實例和適當的參數集,便可以用該參數集調用此委托實例的所有方法。委托實例的一個有趣和有用的屬性是它不了解或不關心它所封裝的方法的類;真正重要的只是方法要與委托的類型兼容, 這使委托非常適合「匿名」調用。可選的形參表指定委托的參數,而返回類型則指示委托的返回類型。如果下面兩個條件都爲真,則方法和委托類型是兼容的:(兼容的概念就是可以用此聲明的委托對方法進行委托).

1它們具有相同的參數數目,並且類型相同,順序相同,參數修飾符也相同。

2它們的返回類型相同。

C# 中的委托類型是名稱等效的,而不是結構等效的。(但是請注意:兩個不同但結構上等效的委托類型的實例可能會比較爲相等),准確地說,兩個具有相同參數列表、簽名和返回類型的不同的委托類型被認爲是不同的委托類型。委托實例所封裝的方法集合稱爲調用列表。

5, interface(接口)

[attributes] [modifiers] interface identifier [:base-list] {interface-body}[;]

一個接口定義一個協定。實現接口的類或結構必須遵守其協定。接口可以從多個基接口繼承,而類或結構可以實現多個接口。接口可以包含方法、屬性、事件和索引器。接口本身不提供它所定義的成員的實現。接口只指定實現該接口的類或接口必須提供的成員。接口可以是命名空間或類的成員,並且可以包含下列成員的簽名:方法屬性 索引器.

一個接口可從一個或多個基接口繼承。接口可由類實現。實現的接口的標識符出現在類的基列表中。被繼承的接口稱爲該接口的顯式基接口。當接口具有一個或多個顯式基接口時,在該接口聲明中,接口標識符後跟一個冒號以及由逗號分隔的基接口標識符列表。接口的基接口是顯式基接口及其基接口。換言之,基接口集是顯式基接口、它們的顯式基接口(依此類推)的完全可傳遞的閉包。接口繼承其基接口的所有成員。接口成員是通過 I.M 和 I[A] 形式的成員訪問和索引訪問表達式訪問的,其中 I 是接口類型的實例,M 是該接口類型的方法、屬性或事件,A 是索引器參數列表。接口可以由類和結構實現。爲了指示類或結構實現接口,在該類或結構的基類列表中包含了接口標識符。在實現類或結構中定位接口成員的實現的過程稱爲接口映射。

6,object

object 類類型是所有其他類型的最終基類。C# 中的每種類型都是直接或間接從 object 類類型派生的。可以把任何類型的數值給object類型.

7,string類型

string 類的實例表示 Unicode 字符串。盡管 string 是引用類型,但相等運算符(== 和 !=)被定義爲比較 string 對象(而不是引用)的「值」(7.9.7 字符串相等運算符)。這使得對字符串相等性的測試更爲直觀。字符串爲 string 類型並可寫成兩種形式,即用引號引起來和用 @ 引起來。用引號引起來的字符串括在雙引號 (") 內, 並且可以包含包括換碼序列在內的任何字符用 @ 引起來的字符串以 @ 開頭,並用雙引號引起來。用 @ 引起來的字符串以 @ 開頭,並用雙引號引起來。若要在一個用 @ 引起來的字符串中包括一個雙引號,請使用兩對雙引號:@ 符號的另一種用法是使用碰巧成爲 C# 關鍵字的被引用的 (/reference) 標識符。

8, 修飾符

修飾符作用

訪問修飾符

public

private

internal

protected

指定聲明的類型和類型成員的可訪問性。

訪問不受限制

只有包含該類的成員的類可以訪問

只有當前工程可以訪問

只有包含該成員的類和繼承的類可以訪問

abstract指示某個類只能是其他類的基類。

const指定無法修改字段或局部變量的值。

event聲明一個事件。

extern指示外部實現此方法。

override提供從基類繼承的虛擬成員的新實現。

readonly聲明一個字段,該字段只能賦值爲該聲明的一部分或者在同一類的構造函數中。

sealed指定類不能被繼承。

static聲明屬于類型本身而不是屬于特定對象的成員。

unsafe聲明不安全的上下文。

virtual在派生類中聲明其實現可由重寫成員更改的方法或訪問器。

volatile指示字段可由操作系統、硬件或並發執行的線程等在程序中進行修改。

9,語句

語句是程序指令。除非特別說明,語句都按順序執行。C# 具有下列類別的語句。

類別C# 關鍵字

選擇語句if, else, switch, case

叠代語句do, for, foreach, in, while

跳轉語句break, continue, default, goto, return

異常處理語句throw, try-catch, try-finally

Checked 和 Uncheckedchecked, unchecked

fixed 語句Fixed

lock 語句Lock

(1) foreach 語句爲數組或對象集合中的每個元素重複一個嵌入語句組。foreach 語句用于循環訪問集合以獲取所需信息,但不應用于更改集合內容以避免産生不可預知的副作用。此語句的形式如下:

foreach (type identifier in expression) statement

若要循環訪問集合,集合必須滿足特定的要求。集合類型:

必須是 interface、class 或 struct。

必須包括返回類型的名爲 GetEnumerator 的實例方法,例如 Enumerator(詳見下文)。

Enumerator 類型(類或結構)必須包含:

一個名爲 Current 的屬性,它返回 ItemType 或者可以轉換爲此類型的類型。屬性訪問器返回集合的當前元素。

· 一個名爲 MoveNext 的 bool 方法,它遞增項計數器並在集合中存在更多項時返回 true。

有三種使用集合的方法:

使用上述指導創建一個集合。此集合只能用于 C# 程序。

1. 使用上述指導創建一個一般集合,另外實現 IEnumerable 接口。此集合可用于其他語言(如 Visual Basic)。

2. 在集合類中使用一個預定義的集合。

(2) throw 語句用于發出在程序執行期間出現反常情況(異常)的信號。throw 語句的形式爲:

throw [expression];

expression :異常對象。當在 catch 子句中再次引發當前異常對象時,它被省略。

(3)try –catch語句

try-catch 語句由一個 try 塊和其後所跟的一個或多個 catch 子句(爲不同的異常指定處理程序)構成。try-catch 語句采用下列形式之一:

try try-block

catch (exception-declaration-1) catch-block-1

catch (exception-declaration-2) catch-block-2

...

try try-block catch catch-block

(4) fixed

防止變量被垃圾回收器重定位。

(5) lock

lock 關鍵字將某個語句塊標記爲臨界區。

6. 方法參數

如果爲沒有 ref 或 out 的方法聲明一個參數,則此參數可以具有關聯的值。可以在方法中更改該值,但當控制傳遞回調用過程時,不會保留更改的值。通過使用方法參數關鍵字,可以更改這種行爲。如果沒有ref,out則默認爲值傳遞,雖然可以在方法中修改這個參數的值,但是修改後的值不會還會到調用該方法的程序中.

params :params 關鍵字可以指定在參數數目可變處采用參數的方法參數

ref :引用傳遞

out :

7, namespace(名字空間)

write by cash(天下第七)

2002.01.20

版權所有,翻錄不究

cashcao@msn.com

選擇

我身上攜帶著精神、信仰、靈魂

思想、欲望、怪癖、邪念、狐臭

它們寄生于我身體的家

我必須平等對待我的每一位客人

-----------伊沙:《原則》

我的名字是cash,所以我很功利主義;

我的星像是Leo,所以我很大男人主義;

我的語言是C#,所以我有點兒拿不定主義。

/* 你能看得出來,這不是一篇正規的技術文章,所以若你不小心從裏邊讀到了一個愛情故事,可不要奇怪。有很多人用程序來表述愛情,在其中我能看到有Money,有Girl,有一些還涉及到Sex,但是我沒有找到Love,我始終相信這世上有一種力量直接來自于愛情,到現在仍然相信。*/

C#(讀作C sharp),是Microsoft公司新推出的(?)專爲.NET設計的一門語言,號稱「C/C++家族中第一種面向組件的語言」。很多人覺得它應該像C或者C++,但事實上它更像是java的一個clone,所以作爲入門,讀一下清華大學出版社出版的《Java 語言與面向對象程序設計》可能會對你有所幫助。本文假定你具備一切學習此語言所需的知識,沒有也不要緊,我會在文中盡量列出相關的link,鑒于互聯網瞬息萬變的特點,若某一鏈接不可用,請自行至Google查詢。

如前所述,我是一個獅子座男人,一度我認爲學習Java會使我看起來與衆不同,可是幾個月以後我放棄了這個選擇,我看了論壇裏關于這兩種語言孰優孰劣的討論,最終選擇了C#,請不要問我爲何做出這樣的選擇,很多人認爲中文是世界上最美麗的語言,可是華人世界以外有誰在講漢語? 另外我發現論壇上學習Java的人都非常的有個性,當有人問起學習哪種語言更好時,他會打出幾百個「JAVA」來,填滿整個屏幕,也不說是爲了什麽。我覺得這樣做未免有些太霸道了,如果你說這叫偏執狂我也不反對,雖然我是獅子座,可也不想被人這樣看。

在C#剛剛推出的時候,大多數的程序員都不免吼上兩句——不是因爲高興,而是因爲又多了一種語言。他們覺得現在的語言太多了,沒有必要再多出一種來添亂子。但是當他們看完C#的文檔後又開始高興起來,因爲C#是如此簡單:事實上,簡單正是C#最大的特點。除此之外,它還具有現代、面向對象、類型安全、版本控制、兼容、靈活等特點。詳細介紹請參閱rainbow(一個長著胡子的彩虹)翻譯的<<展現C#>> ,前幾章非常的有趣。

看完了前面幾段,我的朋友提出了不同的意見:C#不是Java的Clone,它只是長得有些像Java而已,其實面向對象、中間語言什麽的也不是什麽新玩意兒,非Sun獨創,有文爲證:華山論劍:C#對Java。另外他對我上一集中說Microsoft越來越不要臉也極爲生氣,因爲相比之下,Sun也不怎麽樣,微軟已經將C#提交設在日內瓦的ECMA(European Computer Manufacturers' Association,國際標准化機構歐洲電子計算機工業會)並獲得批准。Sun就從來沒有將它的Java交給過ECMA,以至于正當Microsoft盡力在Visual J++基礎上拓展Java功能,並使之與Windows操作系統緊密結合在一起的時候,Sun公司對Microsoft提出了法律訴訟,控告Microsoft違反了許可證協議中的條款,最終的結果是Microsoft公司不得不停止其Visual J++産品的開發。(Microsoft後來在完全面向.NET框架的開發語言集中加入了Visual J#.NET,算是對Java語言用戶的一種照顧。)

有人說,選擇C#意味著選擇MS(在中國的程序員當中,這並不是件值得自豪的事。如果你還不能理解這種心情,可以試想一下有人很認真地對你講他喜歡聽毛甯的歌)。事實上,通過ECMA標准的C#可以由任何人在任何平台上設計出它的開發程序。比如Ximian公司的Mono工程,可以使開發者能夠編寫同時在Windows和Linux上運行的.Net程序,這些程序甚至還可能在其它非Windows的操作系統上運行,比方Unix。這一段時間我正在Linux下試驗這個工程,遺憾的是,還沒有成功。

一位師兄對此種比較頗爲不屑,他認爲只要選一種語言去學就好了,「重要的是你要用它,並且做的比別人好。」這讓我想起來一直都很喜歡的那個歌:把你自己該做的那份工作,做得比別人出色。年輕的時候我老是用這句話自勉……

寫到這裏我發現這個故事還沒有提到桐桐,這篇東西是爲她而作。我早在十八個月以前就答應了她,我答應了她很多事,但還沒有完成一件,現在我要一件一件的去實現。所以這個故事還應該有個更好的開始。

2000年6月我大學畢業,從北京回到了石家莊,到一家什麽都做的公司上班(做一個網站),最開始制作界面,然後用asp編程,如果你用過asp就會知道,這是個很無聊的工種。在此之前我在一家報社實習,爲他們的網站做設計和動畫。在那裏我認識了桐桐。

那時候她還在上學。

>>>未完,待續...

附:本文有關鏈接

展現C#:http://www.csdn.net/Author/Rainbow/

華山論劍:C#對Java:http://www.ccidnet.com/html/tech/guide/2001/06/29/58_2482.html

ECMA:http://www.zdnet.com.cn/developer/tech/story/0,2000081602,20035735-1,00.htm

ECMA批准C#:http://msdn.microsoft.com/net/ecma/

Visual J#.NET:http://www.techng.com/content.asp?titleid=3108

Mono工程:http://www.zdnet.com.cn/developer/news/story/0,2000081594,20032287-1,00.htm

www.go-mono.com

written by cash (天下第七)

版權所有,翻錄不究

cashcao@msn.com

開始

2000年6月我大學畢業,從北京回到了石家莊,正式開始了我的職業生涯。如前所述,一開始我使用的語言是asp,我一直認爲這不能稱之爲編程,因爲asp不是一種編程語言,把它叫做動態網頁實現技術可能更好。另外,asp很簡單,並且,簡單就是它全部的特點--這使得它很容易就能學會(在後來的工作中,我接觸到許多應聘的學生,他們都告訴我自己精通asp語言)。雖然學習起來很簡單,但是在使用起來卻不得不多費點兒勁兒:我還能記得自己晚上一個人在辦公室用VI一步一步調試某一個網頁的情景,每當遇到挫折失敗的時候,總是想起給桐桐打一個電話,聽聽她的聲音。如你所知,我總是遇到困難。

現在你能看出來,我不是高手,只是一個低手...

2000年6月我大學畢業,從北京回到了石家莊,同一時間(美國西部時間6月22日上午),微軟公司在位于美國西雅圖郊外的總部內邀請新聞記者、新聞分析家等約400人,舉行了新聞發布會「Forum2000」,宣布正式推出.Net計劃。這個計劃中包括了新的網絡計算平台(.Net Framework)、新的語言(C#)、新的開發工具(Visual Studio.Net)以及asp的下一個版本ASP.NET,後者最開始被稱爲ASP+。那時候我學習的主要興趣就在ASP.NET上,並且通過這個窗口開始了解Microsoft.Net的各個方面。

ASP.NET仍然不能稱之爲一種編程語言,但是現在可以把它看作是一個創建、管理、部署Web應用程序的平台。可以使用任何.Net語言在這個平台上開發互聯網應用程序,這其中當然包括C#。它們之間的關系可以從下圖中看出:

這就是著名的.Net 平台結構圖,從這個圖上可以看到,ASP.NET、Windows Forms和VS.Net都不過是.Net開發平台的一部分,用于.Net應用程序的開發及展示。.Net 平台的核心技術爲:通用語言運行時(CLR:Common Language Runtime)、基類庫(Base Class Library)、.Net語言及Visual Studio.Net。

從這個圖上也可以看出,.Net Framework是架構在Windows平台上的一個虛擬的運行平台,你可以想象將最下層的Windows換作其它的操作系統,比如說Linux,一樣可以實現使用符合了CLS(Common Language Specification,通用語言規範)的.Net語言(VB.Net、C#、JScript.Net等)來創建ASP.NET或Windows Forms(可能會叫做Linux Forms)應用程序的功能,這其實就是我們前面介紹的Mono計劃所要實現的功能。所以可以這麽認爲,理論上,C#是一種可以跨平台的語言,這很像Java,另一個比較像Java的地方是,C#也是一種(特殊意義上的)解釋性的語言。同Java一樣,C#編寫的程序代碼也是先通過C#編譯器編譯爲一種特殊的字節代碼(中間語言,Microsoft Intermediate Language,MSIL),運行的時候再經由特定的編譯器(JIT編譯器,Just In Time,JITer)編譯爲機器代碼以供操作系統執行。

不僅是C#語言,所有.Net語言(將會包括我們常用的幾十種現代的編程語言)都可以編寫面向CLR的程序代碼,這種代碼在.Net中被稱爲托管代碼(Managed Code),所有的Managed Code都直接運行在CLR上,具有與平台無關的特性。

解釋性的語言很安全,並且可以通過它的運行平台爲其賦予更多的功能,比如自動內存管理、異常處理等。事實上,C#語言的許多特點都是由CLR提供的,下面的CLR結構圖說明了這一點。

可以看到,類型安全(Type Checker)、垃圾回收(Garbage Collector)、異常處理(Exception Manager)、向下兼容(COM Marshaler)、多線程支持(Thread Support)這些C#的特點都是由CLR來提供的。CLR最早被稱爲下一代Windows服務運行時(NGWS Runtime),是直接建立在操作系統層上的一個虛擬的運行環境,主要的功能是管理代碼的運行。在.Net 平台結構圖中,CLR的上面是.Net的基類庫(Base Class Library,BCL),這組基類庫包括了從基本輸入輸出到數據訪問等各方面,提供了一個統一的面向對象的、層次化的、可擴展的編程接口。從.Net 平台結構圖中也可以看到,基類庫可以被各種語言調用和擴展,也就是說,不管是C#、VB.NET還是VC++.NET,都可以自由地調用.Net的基類庫。事實上, C#並沒有屬于自己的類庫,它所使用的編程接口就是.Net提供的基類庫。所以,在決定使用C#時,真正需要費工夫學習的其實是.NET框架的基類庫:C#自身只有區區77個關鍵詞,而且其語法對許多程序員來說都是他們非常熟悉的。BCL則相反,它包含了超過4500個以上的類和無數的方法、屬性,在你的C# 程序中隨時都可能會用到它來完成自己的任務。

很多人都思考過應如何開始學習一種新的語言,對于一個有經驗的編程人員來講,這確非難事。但是對于一個對編寫代碼一無所知的人而言,如果你是以C#開始你的編程之旅的,數目繁多的概念及新名詞可能會令你有些不知所措。這時候請注意你的學習順序,任何一種編程語言的學習都是按照運行平台、語法、基類庫直至各方面的應用這一順序來進行的,但是在實際的學習中,它們之間並不是孤立的。推薦的方法是:對運行平台和語法有了一個整體的認識後,在應用中學習各種基類庫的用法。鑒于C#這一語言的特殊性,全面了解它的運行平台(.NetFramework)必會使你的學習事半功倍。所以請記住上面提到的兩個圖,在以後的學習中,雖然可能不會明確的涉及到它們,但是在整個C#的學習過程中,它們卻是無處不在的。

還有一個很重要的概念需要你明白,這就是公共語言架構(Common Language Infrastructure ,CLI)。CLI是CLR的一個子集,也就是.NET中最終對編譯成MSIL代碼的應用程序的運行環境進行管理的那一部分。在CLR結構圖中CLI位于下半部分,主要包括類加載器(Class Loader)、實時編譯器(IL To Native Compilers)和一個運行時環境的垃圾收集器(Garbage Collector)。CLI是.Net和CLR的靈魂,CLI爲IL代碼提供運行的環境,你可以將使用任何語言編寫的代碼通過其特定的編譯器轉換爲MSIL代碼之後運行其上,甚至還可以自己寫MSIL代碼在CLI上面運行。如你所知,歐洲計算機制造商協會(ECMA)已經于2001年10月13日批准C#語言規範(ECMA-334)成爲一種新誕生的計算機産業標准。同時國際標准組織ISO也同意該標准進入該組織的審批階段。並且,作爲.Net與CLR的核心部分,CLI與C#也同時獲得了ECMA的批准(ECMA-335)。擁有了C#與CLI這兩項標准,你可以自己寫出能夠運行于任何操作系統上的.Net平台(只要你願意)。如前所述,著名的Mono項目就是這麽幹的,Mono項目包括三個核心的部分:一個C#語言的編譯器,一個CLI和一個類庫。在Java的世界中,這項工作是由SUN公司完成的,SUN針對不同的操作系統開發出相應的Java虛擬機以便讓一個由Java開發的應用程序運行在不同的操作系統上,但是迄今爲止還沒聽說過微軟有這方面打算(爲用戶提供非Windows系統的.Net平台)。

2000年的6月還有很多事情發生,2000年的6月我在學校做畢設,晚上就跑到系試驗室看歐錦賽,我很喜歡的坎普君(Bergkamp)大放異彩,幫助荷蘭隊6比1大勝南斯拉夫,米哈伊洛維奇 (Mihajlovic)在比賽最後莫名的笑容永遠留在了我的心中。說實話,那時候只顧著看EURO2000,可沒管什麽.Net、.Not。另外,離別的愁緒圍繞在每個人的周圍,廣播裏開始反反複複播放一些古老的歌曲,不知道爲什麽,戀曲1980卻是那時候的最愛。

後來,我們都畢了業。如你所知,我離開了北京。

written by cash (天下第七)

2002.04.07

版權所有,翻錄不究

cashcao@msn.com

約定

//一個典型的用C#寫就的HelloWorld程序

using System;

class HelloWorld

{

public static void Main()

{

Console.WriteLine("Hello World !");

}

}

我忘記自己第一次用C#向世界問好是在什麽時候了,不過可以肯定我已經打過招呼了,那時候用的是beta1版。現在你可以到http://msdn.microsoft.com/downloads/default.asp?url=/downloads/sample.asp?url=/msdn-files/027/000/976/msdncompositedoc.xml去下載.Net Framework Software Development Kit (SDK)的正式版,其中包括了前面提到的.NET Framework, 以及書寫、編譯、測試、開發 .NET Framework 應用程序所需要的一切——文檔、例子、命令行工具和編譯器。安裝之後就可以開發和運行C#程序了,不過一般的建議是:一定要看.Net Framework SDK中所帶的文檔與例子,如果能照著例子再寫一遍那就再好不過了。

當我第一次看到C#代碼的時候,同樣認爲它很像Java,一個形象的比喻是:C#和Java是一對雙胞胎,從語法的角度來講,它們共同的父親當然非C++莫屬(請注意,不是VC++)。對于一個學過Java語言的人來說(比如說在下),要理解這段代碼實在是太容易了:第一行當然是注釋了,C#支持兩種注釋方法,以"//"開始的單行注釋和以"/*"、"*/"配對使用的多行注釋。第二行(using System)導入了System這個包(在C#中被稱之爲名字空間,Namespace),可以讓我們方便的調用Microsoft.Net基類庫System中的所有類,在此例中使用了System名字空間中的"Console"類,用于在控制台窗口輸出程序運行結果。如前所述,C#並沒有內置的輸入輸出語句,所有需實現的功能都完全來自于.Net基類庫。這一句的作用就是告訴編譯器去哪裏尋找Console類以便調用。

接下來聲明了一個類HelloWorld,這個類中有一個特殊的方法Main(),每個可執行文件都需要有一個入口點,在C#中,這個入口點就是Main()方法,此方法將在程序啓動時被調用。在這個方法中,Console是在命名空間System下的一個類,它表示的是控制台。這裏調用其靜態方法WriteLine()。如同C++一樣,靜態方法允許我們直接作用于類而非實例對象。WriteLine()函數接受字符串類型的參數"Hello World !",並把它送入控制台顯示。如前所述,C#沒有自己的類庫,它直接獲取Microsoft.NET系統類庫。在這裏正是通過獲取Microsoft.NET系統類庫中的System.Console.WriteLine()來完成我們想要的控制台輸出操作。現在使用記事本來編寫這段代碼,並將它的文件名保存爲HelloWorld.cs,其中".cs"是C#源代碼文件的擴展名。然後在配置好C#編譯器的命令行環境裏鍵入"csc HelloWorld.cs"編譯文件。可以看到編譯輸出文件HelloWorld.exe。鍵入HelloWorld執行這個文件可得到下面的輸出:

Hello World !

這就是第一個C#的程序,我們使用csc.exe來編譯它,對于這個C#編譯器,有如下說明:

1.它是隨.Net Framework SDK免費發布的,可以在DOS命令行被調用

2.它的使用方法如下:

csc SourceFile.cs /out:TargetFile.exe

如果不使用輸出參數指定目標文件名,則默認輸出爲源文件名

3.一般情況下,它在系統文件夾(Windows或WinNT)下的Microsoft.NETFrameworkv1.0.3705文件夾內

4.如果你安裝了VS.Net,從Visual Studio.NET Tools項目組中可以激活Visual Studio.NETCommand Prompt窗口,這是一個配置好C#編譯器的命令行環境

5.使用csc.exe編譯後的C#程序並不是機器代碼(盡管擁有.exe的後綴名)。如前所述,C#程序只是被編譯成了MSIL代碼。

C#編譯器(csc.exe)編譯後的文件並不是一個嚴格意義上的可執行文件(並不包含機器代碼),而是一個PE(portable executable)格式的文件,雖然它同樣擁有.exe的後綴名。在這個PE文件中也不僅僅只包含中間語言,在其中還包含有元數據(Metadata)和一個由編譯器添加的目標平台的標准可執行文件頭。

中間語言,確切地說,應該稱爲微軟中間語言(Microsoft Intermediate Language,MSIL),是由微軟定義的一種界于源代碼與機器碼之間的一種語言。在CLR中,它首先會由特定的語言編譯器將其包裝成exe格式的僞代碼(P代碼)。再由特定的編譯器將其轉換爲本地代碼執行。對于微軟中間語言,一個形象的比喻是:如果CLR是操作系統的話,那麽微軟中間語言就是.Net平台上的ASM彙編語言。它比大多數 CPU 機器語言更爲高級,比如它可以理解對象類型,並具有創建和初始化對象、調用關于對象的虛擬方法以及直接操作處理數組元素的指令。它甚至還具有發現和捕獲異常情況用于錯誤處理的指令。

元數據(Metadata)和MSIL共同存在于編譯好的程序文件之中,描述了此程序包含的類型的定義、各種類型的簽名及其它一些數據,相當于以前的類型庫(Type Library),同時也記載了此程序所引用到的其它外部類。元數據的主要作用是將與代碼有關的更多的信息提供給CLR。基本上,元數據用于如下各項任務:用于表示CLR用途的信息,如定位和裝載類、內存中這些類的實例、解決調用、翻譯IL爲原始碼、加強安全並設置運行時上下文邊界。

一個由C#語言寫就的源碼文件在CLR環境中執行的過程是這樣的:首先由C#編譯器編譯成包含了中間語言和元數據的PE文件,當我們在系統中調用這個文件時,CLR會啓動一個編譯器再將這個PE文件包含的MSIL代碼轉換成爲托管的本地代碼。轉換MSIL代碼爲本地碼的這個編譯器就叫做JIT編譯器(Just In Time,JITer)。請注意它並不是前面我們用到的C#編譯器。

現在讓我們看看JIT編譯器是如何工作的:當PE文件被調用時,JIE編譯器將其分解爲MSIL和元數據,這時候MSIL並不直接讓.Net去調用本地的系統接口,而是指定.Net系統去編譯連接那些需要的CLRDLL,編譯出百分之百的本地代碼。整個的過程如下:

當一個類型被裝載時,裝載器創建一個存根(stub),並使它與類型的每一個方法相連接。當一個方法第一次被調用時,存根把控制交給JITer。JITer把MSIL編譯爲本地代碼,並且把存根指針指向緩沖本地代碼。已經被JITer編譯的方法隨後就直接調用已經産生的本地代碼,減少了JITer編譯和執行代碼的時間。可以看到,JITer並不會一次性的將所有的MSIL都編譯爲本地代碼,而是在我們需要時才即時編譯,也就是說,有些代碼可能從來都沒有被編譯過。很明顯這樣做的好處是既保證了運行期的安全性,又不會損失太多的效率。

這就是一個C#程序執行時的步驟。整個過程是這樣的:

1) 由C#編譯器將源代碼編譯爲中間語言

2) 裝入托管代碼,這包括解決內存中的名字、表層類(laying out classes ),並且創建JIT編譯所必需的存根。通過執行經常性校驗,包括加強一些訪問規則,類裝載器同樣也增強了安全性

3) 用JITer將 IL轉換成原始代碼

4) 裝入元數據、校驗類型安全和方法的完整性

5) 垃圾收集(GC)和異常處理

6) 描繪和查錯服務

7) 管理線程和上下文以及遠程管理。

不必全部理解這些概念,在以後的學習中將會一一的體會到它們的精彩,現在你需要做的(如果你還沒這麽幹過的話),是找到ildasm.exe這個文件(一般情況下,它會和csc.exe在同一文件夾中)。顧名思義,這是一個MSIL的反彙編程序(.Net Framework IL Disassembler),在命令行窗口下輸入ildasm helloworld.exe /out=helloworld.il就會得到兩個文件:helloworld.il和helloworld.res。前者包括了反編譯出來的元數據和MSIL代碼,後者則是提取的資源文件。用記事本打開helloworld.il文件,可以看到它定義並實現了一個繼承自System.Object 的HelloWorld類及兩個函數:Main()和.ctor()。其中.ctor()是HelloWorld類的構造函數。在這個文件中還包括元數據和其它有關的信息。如果你覺得這樣不夠直觀的話,可以在命令行窗口鍵入ildasm helloworld.exe,這樣就可以啓動ILDASM 窗口並向我們展示出反編譯後的helloworld.exe文件。

請仔細將這些代碼看上幾遍,現在理解全部這些內容並不重要,但是希望你也能看一下文件中的元數據,這其中包含所有 Runtime 和編譯器需要的有關程序集及其模塊、類型和成員(如方法)的信息。

行文至此,我想談一下學習。如你所知,在我們所處的環境中,學習總意味著是一個痛苦的過程,學習一種新知識好像總是爲了自己的某種需求,我並不認爲這樣有什麽不對,但我總覺著,除了拿到高薪和受人尊敬外,學習還應該帶給我們更多的快樂。有些知識我們現在也許用不著,比如前面談到的一些內容,但是我們了解了,就是一件值得高興的事。

智慧本身就是好的,有一天我們都會死去,追求智慧的道路還會有人在走著。死掉以後的事我看不到。但在我活著的時候,想到這件事,心裏就高興。 ——王小波

今天是2002年4月7號,再過三天就是王小波的忌日了,不知道有多少人還會記得這個日子,還會記得這個人。本文的最後,我向大家推薦小波的作品——每一個心智成熟的人都應該讀一讀小波的文字。在他的雜文隨筆集《沈默的大多數》中有一句話談到了他作爲程序員的一面:

「今晚不把這段C++調通,老子就不睡了!」

1, 結構(struct) 與 類(class) [attributes] [modifiers] struct identifier [:interfaces] body [;] 結構與類很相似,都表示可以包含數據成員和函數成員的數據結構。與類不同的是,結構是值類型並且不需要堆分配。結構類型的變量直接包含結構的數據,而類類型的變量包含對數據的引用(該變量稱爲對象)。 struct 類型適合表示如點、矩形和顔色這樣的輕量對象。盡管可能將一個點表示爲類,但結構在某些方案中更有效。在一些情況下,結構的成本較低。例如,如果聲明一個含有 1000 個點對象的數組,則將爲引用每個對象分配附加的內存。結構可以聲明構造函數,但它們必須帶參數。聲明結構的默認(無參數)構造函數是錯誤的。總是提供默認構造函數以將結構成員初始化爲它們的默認值。在結構中初始化實例字段是錯誤的。在類中,必須初始化實例對象. 使用 new 運算符創建結構對象時,將創建該結構對象,並且調用適當的構造函數。與類不同的是,結構的實例化可以不使用 new 運算符。如果不使用 new,那麽在初始化所有字段之前,字段將保持未賦值狀態且對象不可用。對于結構,不像類那樣存在繼承。一個結構不能從另一個結構或類繼承,而且不能作爲一個類的基。但是,結構從基類 Object 繼承。結構可實現接口,其方式同類完全一樣。 [c++] 與 C++ 不同,無法使用 struct 關鍵字聲明類。在 C# 中,類與結構在語義上是不同的。結構是值類型,而類是引用類型。 2, 裝箱和拆箱(取消裝箱) 裝箱是值類型到 object 類型或到該值類型所實現的任何接口類型的隱式轉換。將一個值的值裝箱會分配一個對象實例並將該值複制到新的對象中。關鍵字 object. 取消裝箱是從 object 類型到值類型或從接口類型到實現該接口的值類型的顯式轉換。取消裝箱操作包括:檢查對象實例,確保它是給定值類型的一個裝箱值。將該值從實例複制到值類型變量中。 例: int i = 123; // A value type object box = i; // Boxing int j = (int)box; // Unboxing 裝箱轉換 取消裝箱 3 , 隱式和顯式 下列轉換屬于隱式轉換:例:object o=i; 標識轉換。 隱式數值轉換。 隱式枚舉轉換。 隱式引用轉換。 裝箱轉換。 隱式常數表達式轉換。 用戶定義的隱式轉換。 下列轉換屬于顯式轉換: object 0=(object)i; 所有隱式轉換。 顯式數值轉換。 顯式枚舉轉換。 顯式引用轉換。 顯式接口轉換。 取消裝箱轉換。 用戶定義的顯式轉換 4, delegate(委托) delegate void D(int x); class C{ public static void M1(int i) { /* ... */ } public static void M2(int i) { /* ... */ }} class{…….D cd1 = new D(C.M1);………….} 委托是一個數據結構,該數據結構引用一個靜態方法,或引用一個對象實例和該對象的實例方法。在 C 或 C++ 中與委托最接近的是函數指針,但函數指針只能引用靜態函數,而委托可以同時引用靜態方法和實例方法。在後一種情況中,委托不僅存儲對方法入口點的引用,還存儲對調用其方法的對象的引用。與 C++ 函數指針不同,委托是完全面對對象的;與指向成員函數的 C++ 指針不同,委托同時封裝對象實例和方法。委托聲明定義從類 System.Delegate 派生的類。委托實例封裝一個或多個方法,每個方法都被稱爲可調用實體。對于實例方法,可調用實體由一個實例和該實例上的方法組成。對于靜態方法,可調用實體僅由一個方法組成。給定委托實例和適當的參數集,便可以用該參數集調用此委托實例的所有方法。委托實例的一個有趣和有用的屬性是它不了解或不關心它所封裝的方法的類;真正重要的只是方法要與委托的類型兼容, 這使委托非常適合「匿名」調用。可選的形參表指定委托的參數,而返回類型則指示委托的返回類型。如果下面兩個條件都爲真,則方法和委托類型是兼容的:(兼容的概念就是可以用此聲明的委托對方法進行委托). 1它們具有相同的參數數目,並且類型相同,順序相同,參數修飾符也相同。 2它們的返回類型相同。 C# 中的委托類型是名稱等效的,而不是結構等效的。(但是請注意:兩個不同但結構上等效的委托類型的實例可能會比較爲相等),准確地說,兩個具有相同參數列表、簽名和返回類型的不同的委托類型被認爲是不同的委托類型。委托實例所封裝的方法集合稱爲調用列表。 5, interface(接口) [attributes] [modifiers] interface identifier [:base-list] {interface-body}[;] 一個接口定義一個協定。實現接口的類或結構必須遵守其協定。接口可以從多個基接口繼承,而類或結構可以實現多個接口。接口可以包含方法、屬性、事件和索引器。接口本身不提供它所定義的成員的實現。接口只指定實現該接口的類或接口必須提供的成員。接口可以是命名空間或類的成員,並且可以包含下列成員的簽名:方法屬性 索引器. 一個接口可從一個或多個基接口繼承。接口可由類實現。實現的接口的標識符出現在類的基列表中。被繼承的接口稱爲該接口的顯式基接口。當接口具有一個或多個顯式基接口時,在該接口聲明中,接口標識符後跟一個冒號以及由逗號分隔的基接口標識符列表。接口的基接口是顯式基接口及其基接口。換言之,基接口集是顯式基接口、它們的顯式基接口(依此類推)的完全可傳遞的閉包。接口繼承其基接口的所有成員。接口成員是通過 I.M 和 I[A] 形式的成員訪問和索引訪問表達式訪問的,其中 I 是接口類型的實例,M 是該接口類型的方法、屬性或事件,A 是索引器參數列表。接口可以由類和結構實現。爲了指示類或結構實現接口,在該類或結構的基類列表中包含了接口標識符。在實現類或結構中定位接口成員的實現的過程稱爲接口映射。 6,object object 類類型是所有其他類型的最終基類。C# 中的每種類型都是直接或間接從 object 類類型派生的。可以把任何類型的數值給object類型. 7,string類型 string 類的實例表示 Unicode 字符串。盡管 string 是引用類型,但相等運算符(== 和 !=)被定義爲比較 string 對象(而不是引用)的「值」(7.9.7 字符串相等運算符)。這使得對字符串相等性的測試更爲直觀。字符串爲 string 類型並可寫成兩種形式,即用引號引起來和用 @ 引起來。用引號引起來的字符串括在雙引號 (") 內, 並且可以包含包括換碼序列在內的任何字符用 @ 引起來的字符串以 @ 開頭,並用雙引號引起來。用 @ 引起來的字符串以 @ 開頭,並用雙引號引起來。若要在一個用 @ 引起來的字符串中包括一個雙引號,請使用兩對雙引號:@ 符號的另一種用法是使用碰巧成爲 C# 關鍵字的被引用的 (/reference) 標識符。 8, 修飾符 修飾符作用 訪問修飾符 public private internal protected 指定聲明的類型和類型成員的可訪問性。 訪問不受限制 只有包含該類的成員的類可以訪問 只有當前工程可以訪問 只有包含該成員的類和繼承的類可以訪問 abstract指示某個類只能是其他類的基類。 const指定無法修改字段或局部變量的值。 event聲明一個事件。 extern指示外部實現此方法。 override提供從基類繼承的虛擬成員的新實現。 readonly聲明一個字段,該字段只能賦值爲該聲明的一部分或者在同一類的構造函數中。 sealed指定類不能被繼承。 static聲明屬于類型本身而不是屬于特定對象的成員。 unsafe聲明不安全的上下文。 virtual在派生類中聲明其實現可由重寫成員更改的方法或訪問器。 volatile指示字段可由操作系統、硬件或並發執行的線程等在程序中進行修改。 9,語句 語句是程序指令。除非特別說明,語句都按順序執行。C# 具有下列類別的語句。 類別C# 關鍵字 選擇語句if, else, switch, case 叠代語句do, for, foreach, in, while 跳轉語句break, continue, default, goto, return 異常處理語句throw, try-catch, try-finally Checked 和 Uncheckedchecked, unchecked fixed 語句Fixed lock 語句Lock (1) foreach 語句爲數組或對象集合中的每個元素重複一個嵌入語句組。foreach 語句用于循環訪問集合以獲取所需信息,但不應用于更改集合內容以避免産生不可預知的副作用。此語句的形式如下: foreach (type identifier in expression) statement 若要循環訪問集合,集合必須滿足特定的要求。集合類型: 必須是 interface、class 或 struct。 必須包括返回類型的名爲 GetEnumerator 的實例方法,例如 Enumerator(詳見下文)。 Enumerator 類型(類或結構)必須包含: 一個名爲 Current 的屬性,它返回 ItemType 或者可以轉換爲此類型的類型。屬性訪問器返回集合的當前元素。 · 一個名爲 MoveNext 的 bool 方法,它遞增項計數器並在集合中存在更多項時返回 true。 有三種使用集合的方法: 使用上述指導創建一個集合。此集合只能用于 C# 程序。 1. 使用上述指導創建一個一般集合,另外實現 IEnumerable 接口。此集合可用于其他語言(如 Visual Basic)。 2. 在集合類中使用一個預定義的集合。 (2) throw 語句用于發出在程序執行期間出現反常情況(異常)的信號。throw 語句的形式爲: throw [expression]; expression :異常對象。當在 catch 子句中再次引發當前異常對象時,它被省略。 (3)try –catch語句 try-catch 語句由一個 try 塊和其後所跟的一個或多個 catch 子句(爲不同的異常指定處理程序)構成。try-catch 語句采用下列形式之一: try try-block catch (exception-declaration-1) catch-block-1 catch (exception-declaration-2) catch-block-2 ... try try-block catch catch-block (4) fixed 防止變量被垃圾回收器重定位。 (5) lock lock 關鍵字將某個語句塊標記爲臨界區。 6. 方法參數 如果爲沒有 ref 或 out 的方法聲明一個參數,則此參數可以具有關聯的值。可以在方法中更改該值,但當控制傳遞回調用過程時,不會保留更改的值。通過使用方法參數關鍵字,可以更改這種行爲。如果沒有ref,out則默認爲值傳遞,雖然可以在方法中修改這個參數的值,但是修改後的值不會還會到調用該方法的程序中. params :params 關鍵字可以指定在參數數目可變處采用參數的方法參數 ref :引用傳遞 out : 7, namespace(名字空間) write by cash(天下第七) 2002.01.20 版權所有,翻錄不究 cashcao@msn.com 選擇 我身上攜帶著精神、信仰、靈魂 思想、欲望、怪癖、邪念、狐臭 它們寄生于我身體的家      我必須平等對待我的每一位客人 -----------伊沙:《原則》 我的名字是cash,所以我很功利主義; 我的星像是Leo,所以我很大男人主義; 我的語言是C#,所以我有點兒拿不定主義。 /* 你能看得出來,這不是一篇正規的技術文章,所以若你不小心從裏邊讀到了一個愛情故事,可不要奇怪。有很多人用程序來表述愛情,在其中我能看到有Money,有Girl,有一些還涉及到Sex,但是我沒有找到Love,我始終相信這世上有一種力量直接來自于愛情,到現在仍然相信。*/ C#(讀作C sharp),是Microsoft公司新推出的(?)專爲.NET設計的一門語言,號稱「C/C++家族中第一種面向組件的語言」。很多人覺得它應該像C或者C++,但事實上它更像是java的一個clone,所以作爲入門,讀一下清華大學出版社出版的《Java 語言與面向對象程序設計》可能會對你有所幫助。本文假定你具備一切學習此語言所需的知識,沒有也不要緊,我會在文中盡量列出相關的link,鑒于互聯網瞬息萬變的特點,若某一鏈接不可用,請自行至Google查詢。 如前所述,我是一個獅子座男人,一度我認爲學習Java會使我看起來與衆不同,可是幾個月以後我放棄了這個選擇,我看了論壇裏關于這兩種語言孰優孰劣的討論,最終選擇了C#,請不要問我爲何做出這樣的選擇,很多人認爲中文是世界上最美麗的語言,可是華人世界以外有誰在講漢語? 另外我發現論壇上學習Java的人都非常的有個性,當有人問起學習哪種語言更好時,他會打出幾百個「JAVA」來,填滿整個屏幕,也不說是爲了什麽。我覺得這樣做未免有些太霸道了,如果你說這叫偏執狂我也不反對,雖然我是獅子座,可也不想被人這樣看。 在C#剛剛推出的時候,大多數的程序員都不免吼上兩句——不是因爲高興,而是因爲又多了一種語言。他們覺得現在的語言太多了,沒有必要再多出一種來添亂子。但是當他們看完C#的文檔後又開始高興起來,因爲C#是如此簡單:事實上,簡單正是C#最大的特點。除此之外,它還具有現代、面向對象、類型安全、版本控制、兼容、靈活等特點。詳細介紹請參閱rainbow(一個長著胡子的彩虹)翻譯的<<展現C#>> ,前幾章非常的有趣。 看完了前面幾段,我的朋友提出了不同的意見:C#不是Java的Clone,它只是長得有些像Java而已,其實面向對象、中間語言什麽的也不是什麽新玩意兒,非Sun獨創,有文爲證:華山論劍:C#對Java。另外他對我上一集中說Microsoft越來越不要臉也極爲生氣,因爲相比之下,Sun也不怎麽樣,微軟已經將C#提交設在日內瓦的ECMA(European Computer Manufacturers' Association,國際標准化機構歐洲電子計算機工業會)並獲得批准。Sun就從來沒有將它的Java交給過ECMA,以至于正當Microsoft盡力在Visual J++基礎上拓展Java功能,並使之與Windows操作系統緊密結合在一起的時候,Sun公司對Microsoft提出了法律訴訟,控告Microsoft違反了許可證協議中的條款,最終的結果是Microsoft公司不得不停止其Visual J++産品的開發。(Microsoft後來在完全面向.NET框架的開發語言集中加入了Visual J#.NET,算是對Java語言用戶的一種照顧。) 有人說,選擇C#意味著選擇MS(在中國的程序員當中,這並不是件值得自豪的事。如果你還不能理解這種心情,可以試想一下有人很認真地對你講他喜歡聽毛甯的歌)。事實上,通過ECMA標准的C#可以由任何人在任何平台上設計出它的開發程序。比如Ximian公司的Mono工程,可以使開發者能夠編寫同時在Windows和Linux上運行的.Net程序,這些程序甚至還可能在其它非Windows的操作系統上運行,比方Unix。這一段時間我正在Linux下試驗這個工程,遺憾的是,還沒有成功。 一位師兄對此種比較頗爲不屑,他認爲只要選一種語言去學就好了,「重要的是你要用它,並且做的比別人好。」這讓我想起來一直都很喜歡的那個歌:把你自己該做的那份工作,做得比別人出色。年輕的時候我老是用這句話自勉…… 寫到這裏我發現這個故事還沒有提到桐桐,這篇東西是爲她而作。我早在十八個月以前就答應了她,我答應了她很多事,但還沒有完成一件,現在我要一件一件的去實現。所以這個故事還應該有個更好的開始。 2000年6月我大學畢業,從北京回到了石家莊,到一家什麽都做的公司上班(做一個網站),最開始制作界面,然後用asp編程,如果你用過asp就會知道,這是個很無聊的工種。在此之前我在一家報社實習,爲他們的網站做設計和動畫。在那裏我認識了桐桐。 那時候她還在上學。 >>>未完,待續... 附:本文有關鏈接 展現C#:http://www.csdn.net/Author/Rainbow/ 華山論劍:C#對Java:http://www.ccidnet.com/html/tech/guide/2001/06/29/58_2482.html ECMA:http://www.zdnet.com.cn/developer/tech/story/0,2000081602,20035735-1,00.htm ECMA批准C#:http://msdn.microsoft.com/net/ecma/ Visual J#.NET:http://www.techng.com/content.asp?titleid=3108 Mono工程:http://www.zdnet.com.cn/developer/news/story/0,2000081594,20032287-1,00.htm www.go-mono.com written by cash (天下第七) 版權所有,翻錄不究 cashcao@msn.com 開始 2000年6月我大學畢業,從北京回到了石家莊,正式開始了我的職業生涯。如前所述,一開始我使用的語言是asp,我一直認爲這不能稱之爲編程,因爲asp不是一種編程語言,把它叫做動態網頁實現技術可能更好。另外,asp很簡單,並且,簡單就是它全部的特點--這使得它很容易就能學會(在後來的工作中,我接觸到許多應聘的學生,他們都告訴我自己精通asp語言)。雖然學習起來很簡單,但是在使用起來卻不得不多費點兒勁兒:我還能記得自己晚上一個人在辦公室用VI一步一步調試某一個網頁的情景,每當遇到挫折失敗的時候,總是想起給桐桐打一個電話,聽聽她的聲音。如你所知,我總是遇到困難。 現在你能看出來,我不是高手,只是一個低手... 2000年6月我大學畢業,從北京回到了石家莊,同一時間(美國西部時間6月22日上午),微軟公司在位于美國西雅圖郊外的總部內邀請新聞記者、新聞分析家等約400人,舉行了新聞發布會「Forum2000」,宣布正式推出.Net計劃。這個計劃中包括了新的網絡計算平台(.Net Framework)、新的語言(C#)、新的開發工具(Visual Studio.Net)以及asp的下一個版本ASP.NET,後者最開始被稱爲ASP+。那時候我學習的主要興趣就在ASP.NET上,並且通過這個窗口開始了解Microsoft.Net的各個方面。 ASP.NET仍然不能稱之爲一種編程語言,但是現在可以把它看作是一個創建、管理、部署Web應用程序的平台。可以使用任何.Net語言在這個平台上開發互聯網應用程序,這其中當然包括C#。它們之間的關系可以從下圖中看出: 這就是著名的.Net 平台結構圖,從這個圖上可以看到,ASP.NET、Windows Forms和VS.Net都不過是.Net開發平台的一部分,用于.Net應用程序的開發及展示。.Net 平台的核心技術爲:通用語言運行時(CLR:Common Language Runtime)、基類庫(Base Class Library)、.Net語言及Visual Studio.Net。 從這個圖上也可以看出,.Net Framework是架構在Windows平台上的一個虛擬的運行平台,你可以想象將最下層的Windows換作其它的操作系統,比如說Linux,一樣可以實現使用符合了CLS(Common Language Specification,通用語言規範)的.Net語言(VB.Net、C#、JScript.Net等)來創建ASP.NET或Windows Forms(可能會叫做Linux Forms)應用程序的功能,這其實就是我們前面介紹的Mono計劃所要實現的功能。所以可以這麽認爲,理論上,C#是一種可以跨平台的語言,這很像Java,另一個比較像Java的地方是,C#也是一種(特殊意義上的)解釋性的語言。同Java一樣,C#編寫的程序代碼也是先通過C#編譯器編譯爲一種特殊的字節代碼(中間語言,Microsoft Intermediate Language,MSIL),運行的時候再經由特定的編譯器(JIT編譯器,Just In Time,JITer)編譯爲機器代碼以供操作系統執行。 不僅是C#語言,所有.Net語言(將會包括我們常用的幾十種現代的編程語言)都可以編寫面向CLR的程序代碼,這種代碼在.Net中被稱爲托管代碼(Managed Code),所有的Managed Code都直接運行在CLR上,具有與平台無關的特性。 解釋性的語言很安全,並且可以通過它的運行平台爲其賦予更多的功能,比如自動內存管理、異常處理等。事實上,C#語言的許多特點都是由CLR提供的,下面的CLR結構圖說明了這一點。 可以看到,類型安全(Type Checker)、垃圾回收(Garbage Collector)、異常處理(Exception Manager)、向下兼容(COM Marshaler)、多線程支持(Thread Support)這些C#的特點都是由CLR來提供的。CLR最早被稱爲下一代Windows服務運行時(NGWS Runtime),是直接建立在操作系統層上的一個虛擬的運行環境,主要的功能是管理代碼的運行。在.Net 平台結構圖中,CLR的上面是.Net的基類庫(Base Class Library,BCL),這組基類庫包括了從基本輸入輸出到數據訪問等各方面,提供了一個統一的面向對象的、層次化的、可擴展的編程接口。從.Net 平台結構圖中也可以看到,基類庫可以被各種語言調用和擴展,也就是說,不管是C#、VB.NET還是VC++.NET,都可以自由地調用.Net的基類庫。事實上, C#並沒有屬于自己的類庫,它所使用的編程接口就是.Net提供的基類庫。所以,在決定使用C#時,真正需要費工夫學習的其實是.NET框架的基類庫:C#自身只有區區77個關鍵詞,而且其語法對許多程序員來說都是他們非常熟悉的。BCL則相反,它包含了超過4500個以上的類和無數的方法、屬性,在你的C# 程序中隨時都可能會用到它來完成自己的任務。 很多人都思考過應如何開始學習一種新的語言,對于一個有經驗的編程人員來講,這確非難事。但是對于一個對編寫代碼一無所知的人而言,如果你是以C#開始你的編程之旅的,數目繁多的概念及新名詞可能會令你有些不知所措。這時候請注意你的學習順序,任何一種編程語言的學習都是按照運行平台、語法、基類庫直至各方面的應用這一順序來進行的,但是在實際的學習中,它們之間並不是孤立的。推薦的方法是:對運行平台和語法有了一個整體的認識後,在應用中學習各種基類庫的用法。鑒于C#這一語言的特殊性,全面了解它的運行平台(.Net Framework)必會使你的學習事半功倍。所以請記住上面提到的兩個圖,在以後的學習中,雖然可能不會明確的涉及到它們,但是在整個C#的學習過程中,它們卻是無處不在的。 還有一個很重要的概念需要你明白,這就是公共語言架構(Common Language Infrastructure ,CLI)。CLI是CLR的一個子集,也就是.NET中最終對編譯成MSIL代碼的應用程序的運行環境進行管理的那一部分。在CLR結構圖中CLI位于下半部分,主要包括類加載器(Class Loader)、實時編譯器(IL To Native Compilers)和一個運行時環境的垃圾收集器(Garbage Collector)。CLI是.Net和CLR的靈魂,CLI爲IL代碼提供運行的環境,你可以將使用任何語言編寫的代碼通過其特定的編譯器轉換爲MSIL代碼之後運行其上,甚至還可以自己寫MSIL代碼在CLI上面運行。如你所知,歐洲計算機制造商協會(ECMA)已經于2001年10月13日批准C#語言規範(ECMA-334)成爲一種新誕生的計算機産業標准。同時國際標准組織ISO也同意該標准進入該組織的審批階段。並且,作爲.Net與CLR的核心部分,CLI與C#也同時獲得了ECMA的批准(ECMA-335)。擁有了C#與CLI這兩項標准,你可以自己寫出能夠運行于任何操作系統上的.Net平台(只要你願意)。如前所述,著名的Mono項目就是這麽幹的,Mono項目包括三個核心的部分:一個C#語言的編譯器,一個CLI和一個類庫。在Java的世界中,這項工作是由SUN公司完成的,SUN針對不同的操作系統開發出相應的Java虛擬機以便讓一個由Java開發的應用程序運行在不同的操作系統上,但是迄今爲止還沒聽說過微軟有這方面打算(爲用戶提供非Windows系統的.Net平台)。 2000年的6月還有很多事情發生,2000年的6月我在學校做畢設,晚上就跑到系試驗室看歐錦賽,我很喜歡的坎普君(Bergkamp)大放異彩,幫助荷蘭隊6比1大勝南斯拉夫,米哈伊洛維奇 (Mihajlovic)在比賽最後莫名的笑容永遠留在了我的心中。說實話,那時候只顧著看EURO2000,可沒管什麽.Net、.Not。另外,離別的愁緒圍繞在每個人的周圍,廣播裏開始反反複複播放一些古老的歌曲,不知道爲什麽,戀曲1980卻是那時候的最愛。 後來,我們都畢了業。如你所知,我離開了北京。 written by cash (天下第七) 2002.04.07 版權所有,翻錄不究 cashcao@msn.com 約定 //一個典型的用C#寫就的HelloWorld程序 using System; class HelloWorld { public static void Main() { Console.WriteLine("Hello World !"); } } 我忘記自己第一次用C#向世界問好是在什麽時候了,不過可以肯定我已經打過招呼了,那時候用的是beta1版。現在你可以到http://msdn.microsoft.com/downloads/default.asp?url=/downloads/sample.asp?url=/msdn-files/027/000/976/msdncompositedoc.xml去下載.Net Framework Software Development Kit (SDK)的正式版,其中包括了前面提到的.NET Framework, 以及書寫、編譯、測試、開發 .NET Framework 應用程序所需要的一切——文檔、例子、命令行工具和編譯器。安裝之後就可以開發和運行C#程序了,不過一般的建議是:一定要看.Net Framework SDK中所帶的文檔與例子,如果能照著例子再寫一遍那就再好不過了。 當我第一次看到C#代碼的時候,同樣認爲它很像Java,一個形象的比喻是:C#和Java是一對雙胞胎,從語法的角度來講,它們共同的父親當然非C++莫屬(請注意,不是VC++)。對于一個學過Java語言的人來說(比如說在下),要理解這段代碼實在是太容易了:第一行當然是注釋了,C#支持兩種注釋方法,以"//"開始的單行注釋和以"/*"、"*/"配對使用的多行注釋。第二行(using System)導入了System這個包(在C#中被稱之爲名字空間,Namespace),可以讓我們方便的調用Microsoft.Net基類庫System中的所有類,在此例中使用了System名字空間中的"Console"類,用于在控制台窗口輸出程序運行結果。如前所述,C#並沒有內置的輸入輸出語句,所有需實現的功能都完全來自于.Net基類庫。這一句的作用就是告訴編譯器去哪裏尋找Console類以便調用。 接下來聲明了一個類HelloWorld,這個類中有一個特殊的方法Main(),每個可執行文件都需要有一個入口點,在C#中,這個入口點就是Main()方法,此方法將在程序啓動時被調用。在這個方法中,Console是在命名空間System下的一個類,它表示的是控制台。這裏調用其靜態方法WriteLine()。如同C++一樣,靜態方法允許我們直接作用于類而非實例對象。WriteLine()函數接受字符串類型的參數"Hello World !",並把它送入控制台顯示。如前所述,C#沒有自己的類庫,它直接獲取Microsoft.NET系統類庫。在這裏正是通過獲取Microsoft.NET系統類庫中的System.Console.WriteLine()來完成我們想要的控制台輸出操作。現在使用記事本來編寫這段代碼,並將它的文件名保存爲HelloWorld.cs,其中".cs"是C#源代碼文件的擴展名。然後在配置好C#編譯器的命令行環境裏鍵入"csc HelloWorld.cs"編譯文件。可以看到編譯輸出文件HelloWorld.exe。鍵入HelloWorld執行這個文件可得到下面的輸出: Hello World ! 這就是第一個C#的程序,我們使用csc.exe來編譯它,對于這個C#編譯器,有如下說明: 1. 它是隨.Net Framework SDK免費發布的,可以在DOS命令行被調用 2. 它的使用方法如下:   csc SourceFile.cs /out:TargetFile.exe   如果不使用輸出參數指定目標文件名,則默認輸出爲源文件名 3. 一般情況下,它在系統文件夾(Windows或WinNT)下的Microsoft.NETFrameworkv1.0.3705文件夾內 4. 如果你安裝了VS.Net,從Visual Studio.NET Tools項目組中可以激活Visual Studio.NET Command Prompt窗口,這是一個配置好C#編譯器的命令行環境 5. 使用csc.exe編譯後的C#程序並不是機器代碼(盡管擁有.exe的後綴名)。如前所述,C#程序只是被編譯成了MSIL代碼。 C#編譯器(csc.exe)編譯後的文件並不是一個嚴格意義上的可執行文件(並不包含機器代碼),而是一個PE(portable executable)格式的文件,雖然它同樣擁有.exe的後綴名。在這個PE文件中也不僅僅只包含中間語言,在其中還包含有元數據(Metadata)和一個由編譯器添加的目標平台的標准可執行文件頭。 中間語言,確切地說,應該稱爲微軟中間語言(Microsoft Intermediate Language,MSIL),是由微軟定義的一種界于源代碼與機器碼之間的一種語言。在CLR中,它首先會由特定的語言編譯器將其包裝成exe格式的僞代碼(P代碼)。再由特定的編譯器將其轉換爲本地代碼執行。對于微軟中間語言,一個形象的比喻是:如果CLR是操作系統的話,那麽微軟中間語言就是.Net平台上的ASM彙編語言。它比大多數 CPU 機器語言更爲高級,比如它可以理解對象類型,並具有創建和初始化對象、調用關于對象的虛擬方法以及直接操作處理數組元素的指令。它甚至還具有發現和捕獲異常情況用于錯誤處理的指令。 元數據(Metadata)和MSIL共同存在于編譯好的程序文件之中,描述了此程序包含的類型的定義、各種類型的簽名及其它一些數據,相當于以前的類型庫(Type Library),同時也記載了此程序所引用到的其它外部類。元數據的主要作用是將與代碼有關的更多的信息提供給CLR。基本上,元數據用于如下各項任務:用于表示CLR用途的信息,如定位和裝載類、內存中這些類的實例、解決調用、翻譯IL爲原始碼、加強安全並設置運行時上下文邊界。 一個由C#語言寫就的源碼文件在CLR環境中執行的過程是這樣的:首先由C#編譯器編譯成包含了中間語言和元數據的PE文件,當我們在系統中調用這個文件時,CLR會啓動一個編譯器再將這個PE文件包含的MSIL代碼轉換成爲托管的本地代碼。轉換MSIL代碼爲本地碼的這個編譯器就叫做JIT編譯器(Just In Time,JITer)。請注意它並不是前面我們用到的C#編譯器。 現在讓我們看看JIT編譯器是如何工作的:當PE文件被調用時,JIE編譯器將其分解爲MSIL和元數據,這時候MSIL並不直接讓.Net去調用本地的系統接口,而是指定.Net系統去編譯連接那些需要的CLR DLL,編譯出百分之百的本地代碼。整個的過程如下: 當一個類型被裝載時,裝載器創建一個存根(stub),並使它與類型的每一個方法相連接。當一個方法第一次被調用時,存根把控制交給JITer。JITer把MSIL編譯爲本地代碼,並且把存根指針指向緩沖本地代碼。已經被JITer編譯的方法隨後就直接調用已經産生的本地代碼,減少了JITer編譯和執行代碼的時間。可以看到,JITer並不會一次性的將所有的MSIL都編譯爲本地代碼,而是在我們需要時才即時編譯,也就是說,有些代碼可能從來都沒有被編譯過。很明顯這樣做的好處是既保證了運行期的安全性,又不會損失太多的效率。 這就是一個C#程序執行時的步驟。整個過程是這樣的: 1) 由C#編譯器將源代碼編譯爲中間語言 2) 裝入托管代碼,這包括解決內存中的名字、表層類(laying out classes ),並且創建JIT編譯所必需的存根。通過執行經常性校驗,包括加強一些訪問規則,類裝載器同樣也增強了安全性 3) 用JITer將 IL轉換成原始代碼 4) 裝入元數據、校驗類型安全和方法的完整性 5) 垃圾收集(GC)和異常處理 6) 描繪和查錯服務 7) 管理線程和上下文以及遠程管理。 不必全部理解這些概念,在以後的學習中將會一一的體會到它們的精彩,現在你需要做的(如果你還沒這麽幹過的話),是找到ildasm.exe這個文件(一般情況下,它會和csc.exe在同一文件夾中)。顧名思義,這是一個MSIL的反彙編程序(.Net Framework IL Disassembler),在命令行窗口下輸入ildasm helloworld.exe /out=helloworld.il就會得到兩個文件:helloworld.il和helloworld.res。前者包括了反編譯出來的元數據和MSIL代碼,後者則是提取的資源文件。用記事本打開helloworld.il文件,可以看到它定義並實現了一個繼承自System.Object 的HelloWorld類及兩個函數:Main()和.ctor()。其中.ctor()是HelloWorld類的構造函數。在這個文件中還包括元數據和其它有關的信息。如果你覺得這樣不夠直觀的話,可以在命令行窗口鍵入ildasm helloworld.exe,這樣就可以啓動ILDASM 窗口並向我們展示出反編譯後的helloworld.exe文件。 請仔細將這些代碼看上幾遍,現在理解全部這些內容並不重要,但是希望你也能看一下文件中的元數據,這其中包含所有 Runtime 和編譯器需要的有關程序集及其模塊、類型和成員(如方法)的信息。 行文至此,我想談一下學習。如你所知,在我們所處的環境中,學習總意味著是一個痛苦的過程,學習一種新知識好像總是爲了自己的某種需求,我並不認爲這樣有什麽不對,但我總覺著,除了拿到高薪和受人尊敬外,學習還應該帶給我們更多的快樂。有些知識我們現在也許用不著,比如前面談到的一些內容,但是我們了解了,就是一件值得高興的事。 智慧本身就是好的,有一天我們都會死去,追求智慧的道路還會有人在走著。死掉以後的事我看不到。但在我活著的時候,想到這件事,心裏就高興。 ——王小波 今天是2002年4月7號,再過三天就是王小波的忌日了,不知道有多少人還會記得這個日子,還會記得這個人。本文的最後,我向大家推薦小波的作品——每一個心智成熟的人都應該讀一讀小波的文字。在他的雜文隨筆集《沈默的大多數》中有一句話談到了他作爲程序員的一面: 「今晚不把這段C++調通,老子就不睡了!」
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
王朝網路微信公眾號
微信掃碼關註本站公眾號 wangchaonetcn
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有