Share via


逐步解說:使用 Visual C# 撰寫元件

元件以物件的形式提供可重複使用的程式碼。 藉由建立物件及呼叫其屬性和方法來使用元件程式碼的應用程式,稱為「用戶端」(Client)。 用戶端與它所使用的元件不一定在同一個組件中。

下列程序將會相互建置,因此執行它們的順序是相當重要的。

注意事項注意事項

根據您目前使用的設定或版本,您所看到的對話方塊與功能表指令可能會與 [說明] 中描述的不同。 若要變更設定,請從 [工具] 功能表中選取 [匯入和匯出設定]。 如需詳細資訊,請參閱 使用設定

建立專案

若要建立 CDemoLib 類別庫及 CDemo 元件

  1. 在 [檔案] 功能表上選取 [新增],然後按一下 [專案],開啟 [新增專案] 對話方塊。 從 Visual C# 專案類型清單選取 [類別庫] 專案範本,然後在 [名稱] 方塊中輸入 CDemoLib。

    注意事項注意事項

    建立新的專案時,一定要指定名稱。 如此可設定預設命名空間、組件名稱及專案名稱,同時也可確定預設元件會在正確的命名空間中。

  2. 在 [方案總管] 中以滑鼠右鍵按一下 [CDemoLib],並從捷徑功能表中選取 [屬性]。 請注意 [預設命名空間] 方塊中包含有 [CDemoLib]。

    預設命名空間是用來限定組件中的元件名稱。 例如,若有兩個組件提供名為 CDemo 的元件,您就可以使用 CDemoLib.CDemo 指定 CDemo 元件。

    關閉對話方塊。

  3. 從 [專案] 功能表中選擇 [加入元件]。

  4. 在 [加入新項目] 對話方塊中選取 [元件類別],然後在 [名稱] 方塊中輸入 CDemo.cs。 按一下 [加入] 以建立元件。

    名為 CDemo 的元件會加入至您的類別庫。

  5. 在 [方案總管] 中以滑鼠右鍵按一下 [CDemo.cs],並從捷徑功能表中選擇 [檢視程式碼]。 程式碼編輯器立即開啟。

    請注意 : Component 將緊接在 public partial class CDemo 之後。 本章節指出您的類別所繼承之類別。 依照預設,元件繼承自系統所提供的 Component 類別。 Component 類別為您的元件提供許多功能,包括使用設計工具的能力。

  6. 在 [方案總管] 中,以滑鼠右鍵按一下 [Class1.cs],再選擇 [刪除]。 如此可刪除類別庫所提供的預設類別,因為在這個逐步解說中不會使用到。

  7. 從 [檔案] 功能表中選擇 [全部儲存] 以儲存專案。

加入建構函式和解構函式

建構函式 (Constructor) 控制元件的初始化方式,Finalize 方法則控制它的終止方式。 建構函式及 CDemo 類別之 Finalize 方法中的程式碼,會維護現存之 CDemo 物件個數的執行計數。

若要替 CDemo 類別的建構函式和解構函式加入程式碼

  1. 在 [程式碼編輯器] 中,加入成員變數以維持 CDemo 類別之執行個體的執行總計,以及各執行個體的 ID 編號

    public readonly int InstanceID;
    private static int NextInstanceID = 0;
    private static long ClassInstanceCount = 0;
    

    由於 InstanceCount 及 NextInstanceID 成員變數宣告為 static,因此只存在於類別層次。 存取這些成員之所有 CDemo 的執行個體將使用相同的記憶體位置。 在程式碼內第一次參考到 CDemo 類別時,會將靜態成員初始化。 這可能是在第一次建立 CDemo 物件,或第一次存取其中一個共用成員時進行。

  2. 找到 CDemo 類別的預設建構函式 public CDemo() 和 public CDemo(IContainer container)。 在 Visual C# 中,所有建構函式都具有與類別相同的名稱。 您的元件可以有數個不同參數的建構函式,但是名稱必須都與元件相同。

    注意事項注意事項

    建構函式的存取層級會判斷哪些用戶端可以建立類別的執行個體。

  3. 在建立新的 CDemo 並設定執行個體的 ID 編號時,將下列程式碼加入至 public CDemo() 以增加執行個體的計數。

    注意事項注意事項

    永遠要將程式碼加在呼叫 InitializeComponent 之後。 此時,任何組成元件都已經初始化。

    InstanceID = NextInstanceID ++;
    ClassInstanceCount ++;
    

    做為 readonly 成員,InstanceID 只能在建構函式中設定。

    注意事項注意事項

    熟悉多執行緒處理的使用者將會正確指出,指派 InstanceID 及累加 NextInstanceID 應該是不可部分完成的作業 (Atomic Operation)。 這個及其他與執行緒相關的問題,會在逐步解說:使用 Visual C# 撰寫簡單的多執行緒元件中加以說明。

  4. 在建構函式結尾處加入下列方法:

    ~CDemo()
    {
       ClassInstanceCount --;
    }
    

    這個方法稱為「解構函式」(Destructor),在類別名稱之前以波狀字元 (~) 表示。 記憶體管理員在最後回收 CDemo 物件所佔用的記憶體之前,會呼叫解構函式。 經由實作解構函式,您可以在您的元件從記憶體移除之前先執行清除。 不過,稍後您將在這個逐步解說中了解,早一點釋放資源有其充分的原因。

將屬性加入至類別

CDemo 類別只有一個屬性,此屬性是靜態屬性,可讓用戶端知道在任何指定的時間內,記憶體中有多少 CDemo 物件。 您也可以用類似的方式建立方法。

若要建立 CDemo 類別的屬性

  • 將下列屬性宣告加入至 CDemo 類別,使用戶端能擷取 CDemo 之執行個體的數目。

    public static long InstanceCount
       {
          get
          {
             return ClassInstanceCount;
          }
       }
    

測試元件

若要測試元件,您需要有使用該元件的專案。 此專案必須是您按下 [執行] 按鈕時,第一個啟動的專案。

若要加入 CDemoTest 用戶端專案做為方案的起始專案

  1. 在 [檔案] 功能表上指向 [新增],然後選擇 [新增專案] 以開啟 [加入新的專案] 對話方塊。

  2. 選取 [Windows 應用程式] 專案範本,然後在 [名稱] 方塊中輸入 [CDemoTest],接著再按一下 [確定]。

  3. 在 [方案總管] 中,以滑鼠右鍵按一下 [CDemoTest],然後按一下捷徑功能表上的 [設定為啟始專案]。

為了要使用 CDemo 元件,用戶端測試專案必須具有對類別庫專案的參考。 加入參考後,也可以加入 using 陳述式至測試應用程式中,以簡化元件的使用。

若要將參考加入至類別庫專案

  1. 在 [方案總管] 中,以滑鼠右鍵按一下緊接在 [CDemoTest] 下方的 [參考] 節點,再按一下捷徑功能表上的 [加入參考]。

  2. 在 [加入參考] 對話方塊中選取 [專案] 索引標籤。

  3. 按兩下 [CDemoLib] 類別庫專案。 [CDemoLib] 將會出現在 [CDemoTest] 專案的 [參考] 節點之下。

  4. 在 [方案總管] 中,以滑鼠右鍵按一下 [Form1.cs],然後從捷徑功能表選取 [檢視程式碼]。

加入 CDemoLib 的參考可讓您使用 CDemo 元件的完整名稱,也就是 CDemoLib.CDemo。

若要加入 using 陳述式

  • 將下列 using 陳述式加入至 Form1 的 [程式碼編輯器] 最上方的 using 陳述式清單。

    using CDemoLib;
    

    加入 using 陳述式可讓您省略程式庫名稱,並以 CDemo 指稱元件類型。

    現在,您將建立並使用測試程式來測試您的元件。

了解物件存留期

CDemoTest 程式將說明 .NET Framework 的物件存留期 (Lifetime),方法是建立及釋放大量的 CDemo 物件。

若要加入程式碼以建立和釋放 CDemo 物件

  1. 按一下 [Form1.cs [設計]],以返回設計工具。

  2. 從 [工具箱] 的 [所有 Windows Form] 索引標籤中,將 ButtonTimer 拖曳到 Form1 設計介面。

    非視覺化的 Timer 元件會顯示在表單下的個別設計介面上。

  3. 按兩下 [timer1] 圖示,替 Timer1 元件的 Tick 事件建立事件處理方法。 將下列程式碼放置在事件處理方法中。

    this.Text = "CDemo instances: " + CDemo.InstanceCount;
    

    在計時器每次跳動時,表單的標題將顯示目前 CDemo 類別的執行個體計數。 類別名稱是做為靜態的 InstanceCount 屬性的限定詞 (Qualifier) 使用,不需要建立 CDemo 的執行個體來存取靜態成員。

  4. 找出 Form1 (public Form1()) 的建構函式,並將下列程式碼加入至呼叫 InitializeComponent() 之後。

    timer1.Enabled = true;
    

    如此,只要表單一建立,計時器將立刻啟動。

  5. 按一下 [Form1.cs [設計]] 索引標籤,以返回設計工具。

  6. 按兩下 Form1 上的 Button,替此按鈕的 Click 事件建立事件處理方法。 將下列程式碼放置在事件處理方法中。

    CDemo cd;
    int ct;
    for (ct = 0; ct < 1000; ct++)
       cd = new CDemo();
    

    您可能覺得這個程式碼很陌生。 在每個 CDemo 的執行個體建立時,即會釋放前一個執行個體。 當 for 迴圈 (Loop) 結束之後,僅會留下一個 CDemo 的執行個體。 當事件處理方法存在時,甚至會釋放該執行個體,因為變數 cd 會超出範圍。

    不過您可能已經猜到,事情的發展不一定是這樣。

若要執行並偵錯 CDemoTest 和 CDemo 專案

  1. 請按 [F5] 以啟動方案。

    用戶端專案將啟動,並顯示 Form1。 請注意,表單的標題會顯示 "CDemo instances: 0"。

  2. 按一下這個按鈕。 表單的標題應該會顯示 "CDemo instances: 1000"。

    按鈕的 CDemo 事件處理程序結束時,Click 的執行個體應該已經全部釋放。 為什麼沒有終結它們? 簡單來說,記憶體管理員會在背景中,以低優先權終結物件。 只有當在系統的記憶體不足時,才會提高優先權。 此「暫緩」(Lazy) 的記憶體回收配置可提供極快速的物件配置。

  3. 多按按鈕幾次,注意看標題。 在某些時點上,執行個體的數目將會突然下降。 這表示記憶體管理員已歸還一些物件的記憶體。

    注意事項注意事項

    如果已經按了 10 次以上,而 CDemo 執行個體數目沒有減少,您可能需要調整程式碼,讓它可以使用更多的記憶體。 關閉表單返回開發環境,然後將 for 迴圈的重複次數增加到 10000, 然後再次執行專案。

  4. 重複步驟 3。 這次,在記憶體管理員終結更多的物件之前,您將可執行地更久。

    其實,您每重複步驟 3 一次,就可能在記憶體管理員介入之前分配更多的 CDemo 物件。 這是因為愈來愈多的 Visual Studio 被調換,留下更多空間給 CDemo 的執行個體使用。

  5. 關閉表單以返回開發環境。

請參閱

其他資源

使用元件進行程式設計

元件撰寫逐步解說