
整體結構就是宣告類別,類別名稱之後用一對大括弧把定義圍起來,裡頭有屬性 (property) 、建構子 (constructor) 、方法 (method) 的的定義,如果這個類別還需要是可執行的,就得額外定義 main() 方法。我們將上面的定義例子寫成完整的範例程式,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | // 宣告類別名稱 class Demo2 { // 這裡定義屬性 int a; int b; // 這裡定義建構子 public Demo2( int a, int b) { this .a = a; this .b = b; } // 這裡定義方法 public int do_something() { return a + b; } // 這裡定義 Main() 方法 static void Main() { Demo2 demo = new Demo2(11, 22); System.Console.WriteLine(); System.Console.WriteLine( "a = " + demo.a + ", b = " + demo.b); System.Console.WriteLine( "a + b = " + demo.do_something()); System.Console.WriteLine(); } } /* 《程式語言教學誌》的範例程式 檔名:demo2.cs 功能:示範 C# 程式 作者:張凱慶 時間:西元 2012 年 10 月 */ |
先來編譯執行,看看執行出什麼結果囉

程式的執行在 Main() 方法的定義地方
18 19 20 21 22 23 24 25 26 | // 這裡定義 Main() 方法 static void Main() { Demo2 demo = new Demo2(11, 22); System.Console.WriteLine(); System.Console.WriteLine( "a = " + demo.a + ", b = " + demo.b); System.Console.WriteLine( "a + b = " + demo.do_something()); System.Console.WriteLine(); } |
我們在 Main() 中宣告 (declare) 並建立相同 Demo2 型態的物件 demo ,為什麼可以這樣做呢?為什麼要在 Main() 中另外建立物件 (object) ,而非直接存取屬性 a 及 b 呢?答案很簡單,首先,因為 a 與 b 沒有給初值,我們當然可以定義後直接給初值,例如
3 4 5 | // 這裡定義屬性 int a = 11; int b = 22; |
這樣屬性 a 與 b 就各自擁有初值 11 及 22 ,我們的作法卻是
3 4 5 | // 這裡定義屬性 int a; int b; |
屬性通常定義在所有方法之外,通常直接放在大括弧之後,類別宣告的下一行。這裡只有作屬性的宣告,也就是宣告屬性為 int 型態的變數,注意,這裡我們在 int 之後空一格,然後接上屬性的識別字 (identifier) 名稱。
C# 並沒有嚴格限制程式的編排方式,所以只要合乎語法, int 空一格,或空兩格並沒有多大關係,但須小心,如果把 int 跟識別字連結在一起,如 inta 或 intb ,編譯器會認為這是額外的識別字名稱,並非我們想要的 a 或 b 了。
因為我們的目的是宣告類別 Demo2 有哪些屬性,也就是先宣告屬性的資料型態,以及屬性的識別字名稱,屬性的值實際是由建構子所賦予,這也是建構子的主要功能之一。再來看到建構子定義的地方
7 8 9 10 11 | // 這裡定義建構子 public Demo2( int a, int b) { this .a = a; this .b = b; } |
建構子如同方法,但不具有回傳值 (return value) 型態 (type) ,因為建構子的目的就是建立物件 (object) ,因此無須指明回傳值的型態。這裡,建構子有兩個參數 (parameter) ,分別是 a 與 b ,由於名稱和屬性相同,在建構子後面的大括弧,也就是建構子的程式區塊 (block) 中,參數 a 與 b 作為此區塊的區域變數 (local variable) ,屬性名稱 a 與 b 便無法使用,因此我們利用關鍵字 (keyword) this 來存取屬性,並把參數指派 (assignment) 給屬性。
當然,若是屬性名稱與建構子的參數名稱不同,我們可以不用 this 便可直接存取屬性名稱,例如
7 8 9 10 11 | // 這裡定義建構子 public Demo2( int c, int d) { a = c; b = d; } |
這樣的小程式中,怎麼寫倒是看個人喜好,往後陸續介紹 public 、 private ,也就是權限方面的修飾詞 (modifier) 之後,我們會提供另外一種寫法。附帶一提, public 是公開的意思, private 則是私有的意思。
Demo2 只有定義一個方法,也就是 do_something()
13 14 15 16 | // 這裡定義方法 public int do_something() { return a + b; } |
do_something() 回傳兩個屬性的相加值, return 是關鍵字之一,用來在方法中回傳數值。這裡 + 是 C# 的算術運算子 (arithmetic operator) 之一,用來作加法,因此 a + b 構成一個運算式 (expression) ,運算式會有一個計算結果, return 就是回傳這個計算結果。
注意, + 是鍵盤上直接打出來的半形字元,非全形字元 + 。
方法宣告時,除了回傳值型態,就是小括弧中的參數列 (parameter list) ,若無提供參數,小括弧就應該留空,也就是不填進任何東西,類似的,方法若無回傳值,應該宣告為 void ,像是 Main() 就宣告成沒有回傳值的 void 。
我們回到最早的問題,也就是為什麼可以在 main() 中建立與 Demo2 相同的物件?其實原因很簡單,就是 static 的緣故。 static 中文稱為靜態的,由於屬性與方法在類別中合稱為成員 (member) ,宣告為 static 的成員被稱為 static 成員, static 成員屬於類別,非 static 成員屬於物件。
成員屬於類別跟屬於物件到底有什麼不同呢?差別在, static 成員可以直接用類別名稱呼叫,我們不是已經用過很多個 System.Console.WriteLine() 的例子了嗎?
System.Console.WriteLine() |
所以,我們要讓 Demo2 變成可執行的類別,我們就得替 Demo2 加上 Main() 方法的定義,由於 Main() 屬於 static 的成員, static 成員不能存取非 static 成員,這裡所謂的不能,其實是 C# 的語法規則,所以為了使 Demo2 可以測試 Demo2 自己,語法允許我們可以在 Demo2 的 Main() 中建立 Demo2 的物件。
有很難懂嗎?如果我們不想用 Demo2 測試 Demo2 他自己,那我們就得另寫一個含有 Main() 的類別,如 Demo3 ,然後在 Demo3 中的 Main() 建立 Demo2 的物件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // 測試 Demo2 的類別 public class Demo3 { static void Main() { Demo2 demo = new Demo2(11, 22); System.Console.WriteLine(); System.Console.WriteLine( "a = " + demo.a + ", b = " + demo.b); System.Console.WriteLine( "a + b = " + demo.do_something()); System.Console.WriteLine(); } } /* 《程式語言教學誌》的範例程式 檔名:demo3.cs 功能:示範 C# 程式 作者:張凱慶 時間:西元 2012 年 10 月 */ |
Demo3 必須和 Demo2 在相同資料夾內,兩個類別檔案也必須分開編譯 (compile) ...... 嗯, Demo2 、 Demo3 等等講了這麼多名稱,這些都是識別字,我們接下來看看變數命名規則吧!
中英文術語對照 | |
---|---|
類別 | class |
屬性 | property |
建構子 | constructor |
方法 | method |
宣告 | declare |
物件 | object |
識別字 | identifier |
回傳值 | return value |
型態 | type |
物件 | object |
參數 | parameter |
區塊 | block |
區域變數 | local variable |
關鍵字 | keyword |
指派 | assignment |
修飾詞 | modifier |
算術運算子 | arithmetic operator |
運算式 | expression |
參數列 | parameter list |
成員 | member |
編譯 | compile |
您可以繼續參考
基礎篇
相關目錄
回 C# 入門指南
回 C# 教材
回首頁
參考資料
http://msdn.microsoft.com/zh-tw/library/ms173109(v=vs.80).aspx
http://msdn.microsoft.com/zh-tw/library/ms229036%28v=vs.80%29.aspx
http://msdn.microsoft.com/zh-tw/library/ms173110%28v=vs.80%29.aspx
http://msdn.microsoft.com/zh-tw/library/x9afc042%28v=vs.80%29.aspx
http://msdn.microsoft.com/zh-tw/library/ms173113%28v=vs.80%29.aspx
http://msdn.microsoft.com/zh-tw/library/ms173114%28v=vs.80%29.aspx
http://msdn.microsoft.com/zh-tw/library/ace5hbzh%28v=vs.80%29.aspx
4 則留言:
站長你好,我想問問以下幾個問題:
甚麼是"回傳值"?"
回傳值的型態"?
為甚麼定義main()方法要"void"?
"方法"跟"main()方法"的差別是?
"System.Console.WriteLine()"是甚麼東西?
為甚麼要"Demo2 測試 Demo2 他自己"?
我是個超級新手,幾乎沒甚麼背景,不麻煩的話還請站長教導一下,十分感謝!
「回傳值」就是方法回傳的數值, C# 規定方法要有回傳數值,像 main() 宣告為 void ,就表示 main() 沒有回傳數值。
main() 是一種預設的方法, C# 規定每個可執行類別都要有個 main() ,因為這是程式執行的起點。
System.Console.WriteLine() 是 .net 程式庫的東西,用來輸出內容到螢幕上。
至於 Demo2 測試 Demo2 ,這個說法是因為我們在 Demo2 的 main() 建立 Demo2 實體物件。
非常讚的站長好
首先致上深深的敬意,感謝您專業又熱心地為程式設計者披荊斬棘。我因想學c#,因緣際會來到 貴網站。昨天也試發了個問題,一來不知有否成功,二來問題不夠完整。所以今天再次請教,感恩。
請教建構子的問題
建構子是否一定要有?
1. 若是,是否一定要跟類別相同名稱?
2. 若非,是否就無需使用到new?我看一本書的例子,作者寫了一個類別Pulse,但內無建構子Pulse(),可是在宣告後引用,仍使用new Pulse()。這是否意味者,即使未特別寫建構子,仍是要new才可以將類別轉為物件來使用。
再者
1. 若有建構子,可否不使用new做初始化,而直接把宣告的類別拿來當物件用(當然可能會有一些初值的問題)?
2. 若無建構子,但類別中另寫的一個程序(或方法)在設定初值,是否應該在使用該類別(物件)前,就應先呼叫該程序做初使化?並請問,樹莓派中所用的GpioController.GetDefault就是這樣的作法。
黃蓮池 敬問
張貼留言