none
介面與抽象類別 RRS feed

  • 問題

  • 請問這2個有什麼分別呢,
    尤其是介面,我看msdn練習的時候,實在搞不太清楚
    使用介面的時機點在那,還有應該如何撰寫屬於自己的介面
    請各位能解釋或是參考資料

    2009年3月11日 上午 09:48

解答

  • 以下是海 K "csharp language specification.doc" 之後,關於 interface 方面小弟自行整理的筆記(加上一點個人見解),比較偏原則性的描述,希望對你有所幫助 ... (其中如果有錯誤的認知,還請各位大大不吝指正 ...^^)


    ※ inheritance-based polymorphism 是      type-oriented polymorphism;
      interface-based   polymorphism 是 operation-oriented polymorphism,是從 type-oriented polymorphism 中萃取特化出來的。

    ※ interface 是提供 interface-based polymorphism 的機制。每一個 interface member implementation 在其所屬型別之 vTable(method table) 中都有自己獨立的
      entry,所有透過 interface 所進行的呼叫都是 dynamic binding 的呼叫。

    ※ 衍生型別會繼承基礎型別所實現的所有 interface 及 interface member implementation。衍生型別透過 interface re-implementation 對所繼承之 interface 提供
      衍生版本的實作。re-implementation 之於 interface implementation,一如 overriding 之於 virtual function。

    ※ 在 C# 中 inheritance-based polymorphism 與 interface-based polymorphism 是並行的 runtime polymorphism 機制,它們之間唯一的交集是:當 interface
      member implementation 為虛擬函式時,虛擬函式的 dynamic binding 性質依然存在於 interface call 中。換言之在 C# 中 inheritance-based polymorphism
      是凌駕於 interface-based polymorphism 之上的 runtime polymorphism。

    ※ instancing 是 polymorphism 的先決條件,因此 static class 無法擁有 virtual function 與 interface member implementation,而 virtual function
      與 interface member implementation 也不可能被宣告為 static。

    ※ interface member implementation 的 dynamic binding 能力無法透過 class reference 發動,但 virtual function 的 dynamic binding 能力可以透過 interface
      reference 發動。

    ※ interface member 是以函式原型(function prototype)所描述與制定的呼叫規格。由於所有的 interface call 均為 dynamic binding,因此所描述的函式都是
      instance function,且無須亦不可冠以任何與虛擬函式有關的 modifier。

    ※ interface 借用繼承的規則(scope、hiding ...)提供自我組合(合併)的能力,但骨子裡與繼承無關,base interface 與 derived interface 之間其實沒有實質上的
      型別關聯,僅只是 subset 與 superset 的關係。

    ※ 與型別間的繼承情況相同,被 derived interface 成員所隱藏的 base interface 成員其實仍然存在於 derived interface 中,只是通常被 iIMI 連帶滿足(實現)了。

    ※ interface member implementation 實作條件:

      iIMI(implicit Interface Member Implementation):public、prototype 同 interface member 並以 unqualified name 為名稱的 instance function member。
      eIMI(explicit Interface Member Implementation):無 access specifier,prototype 同 interface member 並以明指 interface 之 qualified name 為名稱的 instance function member。

    ※ iIMI:無異於一般公開成員函式,只是其函式原型剛好符合 interface member 的要求因而被視為 interface member 的實作。具有以下特性:

      ◆ 衍生型別能夠以繼承所得之 function member 滿足(實現)基礎類別已實現或未實現的 interface member。
      ◆ 單一 iIMI 便能滿足(實現) interface 及其所有 base interface 中任何規格相符(prototype 相同)的 interface member,
        儘管它們之間可能存在著 hiding 或 ambiguity 的衝突關係。
      ◆ 可以是 virtual function,abstract method 亦被視為合法的 interface member implementation。

    ※ eIMI:是純粹為實現特定單一 interface member 而存在的成員函式,是專屬於單一 interface 的實作,具有以下特性:

      ◆ 只能透過專屬之 interface 喚起。
      ◆ 明確聲明只滿足(實現)專屬 interface 中的單一 member,因此絕不會連帶滿足(實現)任何其它 interface 中 prototype 相同的 interface member。
      ◆ 其識別項(identifier)並不被列入實作型別的 scope 中,因而能與其它 prototype 或 signature 相同的任何成員函式並存於型別中而不會發生衝突。
      ◆ 擁有優先被視為 interface member implementation 的權利(當實作型別中存有其它 prototype 相同的成員函式時)。事實上 interface 的實作型別可以同時實作出
        函式原型完全相同的 function member 與 eIMI。
      ◆ 不可以是 virtual function。(即便可以也無法被 override 或透過 class reference 呼叫)

    ※ 為了能被外界的程式碼喚起,其實 interface member implementation 其實不可能為 non-public。於是 eIMI 非但不能用 public,也不能用其它
      access specifier 修飾。

    ※ eIMI 定義式之 qualified interface name 必須為實際定義 interface member 之 interface,不可為其 derived interface,因為 base interface
      與 derived interface 之間實質上並無繼承關係。

    ※ 當一個型別宣稱實現了某個 interface 時,它必須滿足(實現)該 interface 及其所有直接與間接 base interface 中的所有成員。

    ※ class csX : IBase, IDerived { ... } 中 IBase 介面實作聲明部份是多餘的,但並不是一種錯誤。

    ※ 只要型別中存有條件符合的 function member 即被視為實作了規格對應的 interface member,不論該 function member 是否為繼承所得,亦不論該
      function member 為 iIMI 或 eIMI。因此,interface re-implementation 並不需要重新實作所有的 interface member,事實上,全部 interface
      member 均未重新實作也能順利通過編譯。

    ※ 基礎型別中的 iIMI 可以在衍生型別中被 re-implement 為 eIMI。同樣地,基礎型別中的 eIMI 也可以在衍生型別中被 re-implement 為 iIMI。

    ※ interface member 之間:signature 相同時發生 hiding;prototype 相同時被視為相同的呼叫規格。

    ※ 任何 interface member 之間的 hiding 與 ambiguity 都能透過 eIMI 獲得解決。

    ※ explicit cast 語法可用於明確限定呼叫所採行之 interface,可以在 interface member 之間發生 hiding 或 ambiguity 時指明 interface call 所採取的呼叫途徑。
      此種 cast 執行的是 interface 挑選工作,是編譯階段的作業,沒有任何執行時期成本。

    ※ 若基礎型別以 virtual function 實作 iIMI,那麼衍生型別便能在不做 interface re-implementation 的情況下提供 derived version 之 iIMI。

    ※ 一個型別不可以重覆實現同一 interface,即便是以不同型別參數導入的 generic interface 也不可以。

    ※ 當 interface member 為 property、event 或 indexer 呼叫規格時,iIMI 可以實作 interface member 並未指定的 accessor,但 eIMI 不可以(就算可以也無法被呼叫)。

    ※ 擁有相同函式簽名但不同類型(如一為 method,另一為 property accessor)的兩個 interface member 不可能為單一 interface member implementation 所滿足,
      但也不可能同時於型別中實作兩個函式簽名相同的 iIMI,此時至少有一個 interface member 必須被實作成 eIMI。

    ※ System.Object 的 function member 可以透過任何 interface 喚起。

    ※ 實作 generic interface member(是個 generic method,有自己的獨立型別參數列)時,如果該 member 擁有 type parameter constraint,那麼:

      iIMI:必須宣告等價(equivalent)的 type parameter constraint。
      eIMI:內定延用 interface member 的 type parameter constraint,不可自行宣告任何 type parameter constraint。





    • 已標示為解答 ericstone 2009年3月18日 上午 12:23
    2009年3月12日 下午 02:55

所有回覆

  • 這個問題是非常好的問題,你看MSDN是不會找到答案的.因為這是物件導向(OO)的觀念問題.

    如果照字面解釋很容易,介面與抽項類別的差異就是一個只能定義Function,另一個可以包含資料與程式.

    介面這樣東西最早發展開始普及的就是Java,因以往C++有個非常強大但又非常不好學的東西叫多重繼承,而Java當初標版就是要易學易用(以當時後的程式開發環境而言),所以產生了介面這樣東西,改善了多重繼承的一些非常複雜之狀況,當然改用介面後也衍生出一些問題,某些可以用多重繼承達成的東西單用介面無法達成,進而產生了如雙分派這類的設計模式產生,為了就是應付以前多重繼承改用介面後無法達成的問題處理方式.
    以上是界面產生的原因.

    而你的另一個問題何時該使用?
    這是個相當複雜而龐大的問題,整體而言初學者在不熟OO基礎之下很難應用於實際面.
    這也是目前物件導向最大的問題,很多人都應該有這個情況,讀熟了C#的語法,interface abstract override...等等,也都知道在做甚麼,但實際應用卻不曉得要做甚麼.
    物件導向有個特性,一定要整體架構學會後才有辦法開始應用,單就熟語法而言是沒辦法應用的.
    其實9成以上的程式設計師都在用物件導向語言寫程序式導向的程式.而其中某些人卻認為有在寫物件導向程式.

    2009年3月11日 上午 10:06
  •  那我應該參考那些東西?,能讓自己更了解
    目前只了解類別只能繼承一個類別,可是可以繼承很多介面,
    但是自己在練習時,又覺得介面定義function,在類別中使用,感覺上很模糊
    不太知道要如何定義,自己需要的東西和使用
    2009年3月11日 上午 11:08
  • MSDN看久了,你就知道介面跟類別有很大的不同.
    類別是OO的概念,所以類別是繼承導向的概念.
    介面是能力,契約,匹配的概念,所以介面是實作導向的概念.

    2009年3月12日 上午 12:15
  • HI,

    簡單來說, 是使用與實作的差別, 您可以看一下以下的文章:
    http://www.codeproject.com/KB/cs/abstractsvsinterfaces.aspx
    2009年3月12日 上午 02:01
  •  看了你們的說明,我再去看msdn,
    介面是一個定義的通用的function,可是在不同類別的實作上,
    不就又會造成不同程式碼編寫上差異,那以後再維護方面,不就可能面臨每個function不盡相同上的問題,
    介面無法做到以前的module 上的function嗎?
    而抽象類別好像可以定義某些方法,實作還是在各個類別上,不過就只能繼承一個了,
    無法像介面一樣
    這樣在基本的程式架構上,就需要非常長的規劃時間,將程式功能分門別類囉?
    那這樣是不是要多看物件導向方面的書,系統設計分析也需要嗎?
    2009年3月12日 上午 02:05
  • 以下是海 K "csharp language specification.doc" 之後,關於 interface 方面小弟自行整理的筆記(加上一點個人見解),比較偏原則性的描述,希望對你有所幫助 ... (其中如果有錯誤的認知,還請各位大大不吝指正 ...^^)


    ※ inheritance-based polymorphism 是      type-oriented polymorphism;
      interface-based   polymorphism 是 operation-oriented polymorphism,是從 type-oriented polymorphism 中萃取特化出來的。

    ※ interface 是提供 interface-based polymorphism 的機制。每一個 interface member implementation 在其所屬型別之 vTable(method table) 中都有自己獨立的
      entry,所有透過 interface 所進行的呼叫都是 dynamic binding 的呼叫。

    ※ 衍生型別會繼承基礎型別所實現的所有 interface 及 interface member implementation。衍生型別透過 interface re-implementation 對所繼承之 interface 提供
      衍生版本的實作。re-implementation 之於 interface implementation,一如 overriding 之於 virtual function。

    ※ 在 C# 中 inheritance-based polymorphism 與 interface-based polymorphism 是並行的 runtime polymorphism 機制,它們之間唯一的交集是:當 interface
      member implementation 為虛擬函式時,虛擬函式的 dynamic binding 性質依然存在於 interface call 中。換言之在 C# 中 inheritance-based polymorphism
      是凌駕於 interface-based polymorphism 之上的 runtime polymorphism。

    ※ instancing 是 polymorphism 的先決條件,因此 static class 無法擁有 virtual function 與 interface member implementation,而 virtual function
      與 interface member implementation 也不可能被宣告為 static。

    ※ interface member implementation 的 dynamic binding 能力無法透過 class reference 發動,但 virtual function 的 dynamic binding 能力可以透過 interface
      reference 發動。

    ※ interface member 是以函式原型(function prototype)所描述與制定的呼叫規格。由於所有的 interface call 均為 dynamic binding,因此所描述的函式都是
      instance function,且無須亦不可冠以任何與虛擬函式有關的 modifier。

    ※ interface 借用繼承的規則(scope、hiding ...)提供自我組合(合併)的能力,但骨子裡與繼承無關,base interface 與 derived interface 之間其實沒有實質上的
      型別關聯,僅只是 subset 與 superset 的關係。

    ※ 與型別間的繼承情況相同,被 derived interface 成員所隱藏的 base interface 成員其實仍然存在於 derived interface 中,只是通常被 iIMI 連帶滿足(實現)了。

    ※ interface member implementation 實作條件:

      iIMI(implicit Interface Member Implementation):public、prototype 同 interface member 並以 unqualified name 為名稱的 instance function member。
      eIMI(explicit Interface Member Implementation):無 access specifier,prototype 同 interface member 並以明指 interface 之 qualified name 為名稱的 instance function member。

    ※ iIMI:無異於一般公開成員函式,只是其函式原型剛好符合 interface member 的要求因而被視為 interface member 的實作。具有以下特性:

      ◆ 衍生型別能夠以繼承所得之 function member 滿足(實現)基礎類別已實現或未實現的 interface member。
      ◆ 單一 iIMI 便能滿足(實現) interface 及其所有 base interface 中任何規格相符(prototype 相同)的 interface member,
        儘管它們之間可能存在著 hiding 或 ambiguity 的衝突關係。
      ◆ 可以是 virtual function,abstract method 亦被視為合法的 interface member implementation。

    ※ eIMI:是純粹為實現特定單一 interface member 而存在的成員函式,是專屬於單一 interface 的實作,具有以下特性:

      ◆ 只能透過專屬之 interface 喚起。
      ◆ 明確聲明只滿足(實現)專屬 interface 中的單一 member,因此絕不會連帶滿足(實現)任何其它 interface 中 prototype 相同的 interface member。
      ◆ 其識別項(identifier)並不被列入實作型別的 scope 中,因而能與其它 prototype 或 signature 相同的任何成員函式並存於型別中而不會發生衝突。
      ◆ 擁有優先被視為 interface member implementation 的權利(當實作型別中存有其它 prototype 相同的成員函式時)。事實上 interface 的實作型別可以同時實作出
        函式原型完全相同的 function member 與 eIMI。
      ◆ 不可以是 virtual function。(即便可以也無法被 override 或透過 class reference 呼叫)

    ※ 為了能被外界的程式碼喚起,其實 interface member implementation 其實不可能為 non-public。於是 eIMI 非但不能用 public,也不能用其它
      access specifier 修飾。

    ※ eIMI 定義式之 qualified interface name 必須為實際定義 interface member 之 interface,不可為其 derived interface,因為 base interface
      與 derived interface 之間實質上並無繼承關係。

    ※ 當一個型別宣稱實現了某個 interface 時,它必須滿足(實現)該 interface 及其所有直接與間接 base interface 中的所有成員。

    ※ class csX : IBase, IDerived { ... } 中 IBase 介面實作聲明部份是多餘的,但並不是一種錯誤。

    ※ 只要型別中存有條件符合的 function member 即被視為實作了規格對應的 interface member,不論該 function member 是否為繼承所得,亦不論該
      function member 為 iIMI 或 eIMI。因此,interface re-implementation 並不需要重新實作所有的 interface member,事實上,全部 interface
      member 均未重新實作也能順利通過編譯。

    ※ 基礎型別中的 iIMI 可以在衍生型別中被 re-implement 為 eIMI。同樣地,基礎型別中的 eIMI 也可以在衍生型別中被 re-implement 為 iIMI。

    ※ interface member 之間:signature 相同時發生 hiding;prototype 相同時被視為相同的呼叫規格。

    ※ 任何 interface member 之間的 hiding 與 ambiguity 都能透過 eIMI 獲得解決。

    ※ explicit cast 語法可用於明確限定呼叫所採行之 interface,可以在 interface member 之間發生 hiding 或 ambiguity 時指明 interface call 所採取的呼叫途徑。
      此種 cast 執行的是 interface 挑選工作,是編譯階段的作業,沒有任何執行時期成本。

    ※ 若基礎型別以 virtual function 實作 iIMI,那麼衍生型別便能在不做 interface re-implementation 的情況下提供 derived version 之 iIMI。

    ※ 一個型別不可以重覆實現同一 interface,即便是以不同型別參數導入的 generic interface 也不可以。

    ※ 當 interface member 為 property、event 或 indexer 呼叫規格時,iIMI 可以實作 interface member 並未指定的 accessor,但 eIMI 不可以(就算可以也無法被呼叫)。

    ※ 擁有相同函式簽名但不同類型(如一為 method,另一為 property accessor)的兩個 interface member 不可能為單一 interface member implementation 所滿足,
      但也不可能同時於型別中實作兩個函式簽名相同的 iIMI,此時至少有一個 interface member 必須被實作成 eIMI。

    ※ System.Object 的 function member 可以透過任何 interface 喚起。

    ※ 實作 generic interface member(是個 generic method,有自己的獨立型別參數列)時,如果該 member 擁有 type parameter constraint,那麼:

      iIMI:必須宣告等價(equivalent)的 type parameter constraint。
      eIMI:內定延用 interface member 的 type parameter constraint,不可自行宣告任何 type parameter constraint。





    • 已標示為解答 ericstone 2009年3月18日 上午 12:23
    2009年3月12日 下午 02:55
  • 這樣在基本的程式架構上,就需要非常長的規劃時間,將程式功能分門別類囉?
    那這樣是不是要多看物件導向方面的書,系統設計分析也需要嗎?

    是的,這就是答案

    上面有人很明確的回答介面的定義與說明,但如同我上面所說的,了解介面與繼承等觀念並不是非常困難,我相信很多人也都了解,這些東西最難的地方在於"該如何使用?",而最正確的解答是-經驗.也是是你已經了解的答案看物件導向方面的書與系統設計分析.
    如我之前回覆,物件導向這門學問最困難的地方並不是在看程式本身的語法與語意,而是該如何應用物件導向解決問題,因為如你所想的牽連的範圍太廣泛,注意看市面上針對特定語言的一些書籍,大多只會簡單帶過語法,卻沒告訴讀者要怎麼作,而這些答案通常不是出現在特定語言的書籍中,而是一些系統分析的書籍,但系統分細的書籍大多又偏重在理論面,所以導致讀者很難將兩者直接連貫再一起,唯有多看最後才會慢慢找到答案

    相信很多人都有一種經驗,在網路上找了些用物件導向寫好的程式之Source Code也看得懂要做甚麼,但如果要自己用物件導向的方式開發相同功能的程式卻會發現不知如何著手.

    程序式導向與物件導向最大的差異在於,大多數程序式導向寫出來的程式都是為了達成目的,但物件導向最大的目的是在於如何"寫好程式".
    "寫好程式"的範圍相當廣泛-包含設計架構....但最終的重點只有一個"如何因應需求變化",這是物件導向最大的目標.

    但有兩種情況不適合物件導向開發模
    1.程式寫完就不會任何更改
    2.程式並不大.(所謂不大的定義指得能夠很簡單的應付需求變化).

    2009年3月13日 上午 07:33
  •  忘記回覆如果對物件導向有興趣可以依下面步驟來學習(這是我本身的經驗)
    1.找個物件導像語言先學會語法(如果在學校我非常建議學C++,因為C++會碰觸到的底層觀念比較之多,但相對的也難學很多,很多人搞不懂 C與C++的差異,答案就是物件導向).
    市面上這類書籍很多,但語言為JAVA佔大多數(雖然物件導向語言很多,但Java是推動物件導向最重要的原因),像JAVA 樣式與實例這類的書籍.
    2.如果已經熟悉物件導向的語法,推薦看一本書 敏捷軟體開發 原則樣式與實務,這本書有個優點就是一開始如果沒有實際做過看這本書會發現看得懂意思,但不知道為什麼要這樣做,當你開始應用於實際案例時,碰到問題再來翻翻這本書有時候就會找到答案.就像我之前常用交易的一個Sample Code回答一些問題.一開始我也不清楚為什魔要搞得那麼複雜,後來在實際應用中發現一個困難點再回頭看這個範例終於了解當初作者為何會有這篇文章,這種例子非常多.

    3.這點是最難的,物件導向如同上面所說,看再多的書還是不曉得該如何著手,因為大多數真正再說明物件導向的書籍,在實際應用會碰觸到的問題卻不會提及,原因是範圍太大,每個問題點可能都需要一本專書,舉例來說 你可以設計一個Customer的Class,以物件導向觀念,Customer中可能包含一個Employee集合屬性,但在實際運作上常跟資料庫運作有關係,這時候會發現該如何處理這個問題,而答案很多,ORM是目前最好的方式.  而這些問題在實做上才會遇到,遇到時就必須花很多時間先學習這些技術.
    2009年3月13日 上午 07:51
  •  曾經畢業專題系上要求用輕量化的cmmi模式,看了各位解說,
    想到結構化分析,有內聚力和偶和力(名詞不知道對不對),介面是不是解決程式間的偶和力,
    因為關聯愈多時,也表示日後修改時也會影響他其他功能,而介面只是定義function ,在類別裡實作
    有看到關於鑄型介面,可以將實作介面的類別當成介面方法來使用,那這樣是不是跟vb之前module很類似?
    2009年3月16日 下午 01:29
  • 你說到重點了,不論哪種程式設計方式最終要解決的就是"變化".
    只是目前看起來最合適的大概只有物件導向設計方式能夠應付大多數變化.
    注意看市面上所有系統分析的書籍都會告訴你並未設現在哪種語言或工具,但最終還是跳脫不了物件導向.

    系統分析的書籍如你所知 高內聚力 低偶合度是設計上的重點,但要如何做到是個非常困難的事情.
    諸如開閉原則等等概念,書上寫得很清楚,但困難的是很難直接連貫到實作之上,這也是我上面回覆所說的.
    2009年3月16日 下午 11:40
  • 我想問一個很笨的問題
    A類別是父類別,B、C、D、E是A的子類別
    子類別如果輸入不同id, 也是改變自己的id, 不會改變到別人的嗎?
    class A
    {

      protected string ID

    }

    class   B:A
    {
      public void hallo (string str)
      {
        this.ID =str;
      }
    {
    其他class 以下類推
    2009年3月18日 上午 09:48
  • 類別實例後的物件,有自己的物件變數不會影響別的物件.

    2009年3月18日 上午 10:09
  • 在 C# 中,型別的資料成員(data member)被稱為 field。從資料是否共用的角度來看,可以將所有的 field 分為兩大類:instance field 與 static field。

    instance field 是在型別定義式中不含 static 修飾詞的 field,static field 則是在型別定義式中加冠 static 修飾詞的 field。

    在物件導向的概念中,型別(type,在 C# 中主要為 class 與 struct)是實體(instance)據以生成的藍圖,每一份 instance 都是 type 的單一 "案例"。

    之所以被叫做 "instance" field,是因為這樣的 field 為所有 instance 各自獨立持有。程式執行時,每一個 instance field 都佔有獨立的記憶體空間,一如持有它們的 instance。因此當某個 instance 中的 instance field 受到修改時,其它同型別之 instance 中名稱相同的 instance field 完全不會受到影響。

    而不論一個 type 被產生了多少個 instance(包括其 sub-type 的 instance),其 static field 永遠只有一份,事實上,static field 在整個型別衍生體系中都是唯一的。

    在物件導向的領域裡,instance 與 static 互為反意詞;邏輯上來說,instance field 隸屬於 instance,static field 則隸屬於 type。


    1 using System;  
    2  
    3 namespace Test {  
    4  
    5     class csBase {  
    6         protected        Int32  fldInstance = 0;  
    7         protected static Int32  fldStatic   = 0;  
    8         protected string fldName = null;  
    9     }  
    10  
    11     class csDerived : csBase {  
    12         public csDerived(string name) { fldName = name; }  
    13         public        void InstanceIncrement() { ++fldInstance; }  
    14         public        void StaticIncrement() { ++fldStatic; }  
    15         public static void StaticIncrementS() { ++csBase.fldStatic; }  
    16         public void ShowFields() { Console.WriteLine("fldStatic = {0}, {1}.fldInstance = {2}", fldStatic, fldName, fldInstance); }  
    17     }  
    18  
    19     class Program {  
    20  
    21         static void Main(string[] args) {  
    22  
    23             csDerived d1 = new csDerived("d1"), d2 = new csDerived("d2");  
    24  
    25             d1.InstanceIncrement();  
    26             d1.InstanceIncrement();  
    27             d1.InstanceIncrement();  
    28  
    29             d2.InstanceIncrement();  
    30  
    31             d1.StaticIncrement();  
    32             d2.StaticIncrement();  
    33             csDerived.StaticIncrementS();  
    34  
    35             d1.ShowFields();  
    36             d2.ShowFields();  
    37  
    38             Console.ReadKey();  
    39  
    40         }  
    41  
    42     }  
    43  
    44 }  
    45  


    PS: 誠心建議,一定要好好掌握物件導向的核心觀念!物件導向千變萬化,卻不離其宗(C++)。推薦你買 C++ Primer 3e 與 4e,3e 的中譯本翻譯品質極佳,一定要弄一本入手!個人觀點:C# 其實比 C++ 更複雜,沒有厚實的 C++ 基礎,要學好 C# 並不容易。

    2009年3月19日 上午 01:29