逐步解說:使用 Visual C# 撰寫元件
元件以物件的形式提供可重複使用的程式碼。 藉由建立物件及呼叫其屬性和方法來使用元件程式碼的應用程式,稱為「用戶端」(Client)。 用戶端與它所使用的元件不一定在同一個組件中。
下列程序將會相互建置,因此執行它們的順序是相當重要的。
注意事項 |
---|
根據您目前使用的設定或版本,您所看到的對話方塊與功能表指令可能會與 [說明] 中描述的不同。若要變更設定,請從 [工具] 功能表中選擇 [匯入和匯出設定]。如需詳細資訊,請參閱 Visual Studio 中的自訂開發設定。 |
建立專案
若要建立 CDemoLib 類別庫及 CDemo 元件
在 [檔案] 功能表上選取 [新增],然後按一下 [專案],開啟 [新增專案] 對話方塊。 從 Visual C# 專案類型清單選取 [類別庫] 專案範本,然後在 [名稱] 方塊中輸入 CDemoLib。
注意事項 建立新的專案時,一定要指定名稱。如此可設定預設命名空間、組件名稱及專案名稱,同時也可確定預設元件會在正確的命名空間中。
在 [方案總管] 中以滑鼠右鍵按一下 [CDemoLib],並從捷徑功能表中選取 [屬性]。 請注意 [預設命名空間] 方塊中包含有 [CDemoLib]。
預設命名空間是用來限定組件中的元件名稱。 例如,若有兩個組件提供名為 CDemo 的元件,您就可以使用 CDemoLib.CDemo 指定 CDemo 元件。
關閉對話方塊。
從 [專案] 功能表中選擇 [加入元件]。
在 [加入新項目] 對話方塊中選取 [元件類別],然後在 [名稱] 方塊中輸入 CDemo.cs。 按一下 [加入] 以建立元件。
名為 CDemo 的元件會加入至您的類別庫。
在 [方案總管] 中以滑鼠右鍵按一下 [CDemo.cs],並從捷徑功能表中選擇 [檢視程式碼]。 程式碼編輯器立即開啟。
請注意 : Component 將緊接在 public partial class CDemo 之後。 本章節指出您的類別所繼承之類別。 依照預設,元件繼承自系統所提供的 Component 類別。 Component 類別為您的元件提供許多功能,包括使用設計工具的能力。
在 [方案總管] 中,以滑鼠右鍵按一下 [Class1.cs],再選擇 [刪除]。 如此可刪除類別庫所提供的預設類別,因為在這個逐步解說中不會使用到。
從 [檔案] 功能表中選擇 [全部儲存] 以儲存專案。
加入建構函式和解構函式
建構函式 (Constructor) 控制元件的初始化方式,Finalize 方法則控制它的終止方式。 建構函式及 CDemo 類別之 Finalize 方法中的程式碼,會維護現存之 CDemo 物件個數的執行計數。
若要替 CDemo 類別的建構函式和解構函式加入程式碼
在 [程式碼編輯器] 中,加入成員變數以維持 CDemo 類別之執行個體的執行總計,以及各執行個體的 ID 編號
public readonly int InstanceID; private static int NextInstanceID = 0; private static long ClassInstanceCount = 0;
由於 InstanceCount 及 NextInstanceID 成員變數宣告為 static,因此只存在於類別層次。 存取這些成員之所有 CDemo 的執行個體將使用相同的記憶體位置。 在程式碼內第一次參考到 CDemo 類別時,會將靜態成員初始化。 這可能是在第一次建立 CDemo 物件,或第一次存取其中一個共用成員時進行。
找到 CDemo 類別的預設建構函式 public CDemo() 和 public CDemo(IContainer container)。 在 Visual C# 中,所有建構函式都具有與類別相同的名稱。 您的元件可以有數個不同參數的建構函式,但是名稱必須都與元件相同。
注意事項 建構函式的存取層級會判斷哪些用戶端可以建立類別的執行個體。
在建立新的 CDemo 並設定執行個體的 ID 編號時,將下列程式碼加入至 public CDemo() 以增加執行個體的計數。
注意事項 永遠要將程式碼加在呼叫 InitializeComponent 之後。此時,任何組成元件都已經初始化。
InstanceID = NextInstanceID ++; ClassInstanceCount ++;
做為 readonly 成員,InstanceID 只能在建構函式中設定。
注意事項 熟悉多執行緒處理的使用者將會正確指出,指派 InstanceID 及累加 NextInstanceID 應該是不可部分完成的作業 (Atomic Operation)。這個及其他與執行緒相關的問題,會在逐步解說:使用 Visual C# 撰寫簡單的多執行緒元件中加以說明。
在建構函式結尾處加入下列方法:
~CDemo() { ClassInstanceCount --; }
這個方法稱為「解構函式」(Destructor),在類別名稱之前以波狀字元 (~) 表示。 記憶體管理員在最後回收 CDemo 物件所佔用的記憶體之前,會呼叫解構函式。 經由實作解構函式,您可以在您的元件從記憶體移除之前先執行清除。 不過,稍後您將在這個逐步解說中了解,早一點釋放資源有其充分的原因。
將屬性加入至類別
CDemo 類別只有一個屬性,此屬性是靜態屬性,可讓用戶端知道在任何指定的時間內,記憶體中有多少 CDemo 物件。 您也可以用類似的方式建立方法。
若要建立 CDemo 類別的屬性
將下列屬性宣告加入至 CDemo 類別,使用戶端能擷取 CDemo 之執行個體的數目。
public static long InstanceCount { get { return ClassInstanceCount; } }
測試元件
若要測試元件,您需要有使用該元件的專案。 此專案必須是您按下 [執行] 按鈕時,第一個啟動的專案。
若要加入 CDemoTest 用戶端專案做為方案的起始專案
在 [檔案] 功能表上指向 [新增],然後選擇 [新增專案] 以開啟 [加入新的專案] 對話方塊。
選取 [Windows 應用程式] 專案範本,然後在 [名稱] 方塊中輸入 [CDemoTest],接著再按一下 [確定]。
在 [方案總管] 中,以滑鼠右鍵按一下 [CDemoTest],然後按一下捷徑功能表上的 [設定為啟始專案]。
為了要使用 CDemo 元件,用戶端測試專案必須具有對類別庫專案的參考。 加入參考後,也可以加入 using 陳述式至測試應用程式中,以簡化元件的使用。
若要將參考加入至類別庫專案
在 [方案總管] 中,以滑鼠右鍵按一下緊接在 [CDemoTest] 下方的 [參考] 節點,再按一下捷徑功能表上的 [加入參考]。
在 [加入參考] 對話方塊中選取 [專案] 索引標籤。
按兩下 [CDemoLib] 類別庫專案。 [CDemoLib] 將會出現在 [CDemoTest] 專案的 [參考] 節點之下。
在 [方案總管] 中,以滑鼠右鍵按一下 [Form1.cs],然後從捷徑功能表選取 [檢視程式碼]。
加入 CDemoLib 的參考可讓您使用 CDemo 元件的完整名稱,也就是 CDemoLib.CDemo。
若要加入 using 陳述式
將下列 using 陳述式加入至 Form1 的 [程式碼編輯器] 最上方的 using 陳述式清單。
using CDemoLib;
加入 using 陳述式可讓您省略程式庫名稱,並以 CDemo 指稱元件類型。
現在,您將建立並使用測試程式來測試您的元件。
了解物件存留期
CDemoTest 程式將說明 .NET Framework 的物件存留期 (Lifetime),方法是建立及釋放大量的 CDemo 物件。
若要加入程式碼以建立和釋放 CDemo 物件
按一下 [Form1.cs [設計]],以返回設計工具。
從 [工具箱] 的 [所有 Windows Form] 索引標籤中,將 Button 及 Timer 拖曳到 Form1 設計介面。
非視覺化的 Timer 元件會顯示在表單下的個別設計介面上。
按兩下 [timer1] 圖示,替 Timer1 元件的 Tick 事件建立事件處理方法。 將下列程式碼放置在事件處理方法中。
this.Text = "CDemo instances: " + CDemo.InstanceCount;
在計時器每次跳動時,表單的標題將顯示目前 CDemo 類別的執行個體計數。 類別名稱是做為靜態的 InstanceCount 屬性的限定詞 (Qualifier) 使用,不需要建立 CDemo 的執行個體來存取靜態成員。
找出 Form1 (public Form1()) 的建構函式,並將下列程式碼加入至呼叫 InitializeComponent() 之後。
timer1.Enabled = true;
如此,只要表單一建立,計時器將立刻啟動。
按一下 [Form1.cs [設計]] 索引標籤,以返回設計工具。
按兩下 Form1 上的 Button,替此按鈕的 Click 事件建立事件處理方法。 將下列程式碼放置在事件處理方法中。
CDemo cd; int ct; for (ct = 0; ct < 1000; ct++) cd = new CDemo();
您可能覺得這個程式碼很陌生。 在每個 CDemo 的執行個體建立時,即會釋放前一個執行個體。 當 for 迴圈 (Loop) 結束之後,僅會留下一個 CDemo 的執行個體。 當事件處理方法存在時,甚至會釋放該執行個體,因為變數 cd 會超出範圍。
不過您可能已經猜到,事情的發展不一定是這樣。
若要執行並偵錯 CDemoTest 和 CDemo 專案
請按 [F5] 以啟動方案。
用戶端專案將啟動,並顯示 Form1。 請注意,表單的標題會顯示 "CDemo instances: 0"。
按一下這個按鈕。 表單的標題應該會顯示 "CDemo instances: 1000"。
按鈕的 CDemo 事件處理程序結束時,Click 的執行個體應該已經全部釋放。 為什麼沒有終結它們? 簡單來說,記憶體管理員會在背景中,以低優先權終結物件。 只有當在系統的記憶體不足時,才會提高優先權。 此「暫緩」(Lazy) 的記憶體回收配置可提供極快速的物件配置。
多按按鈕幾次,注意看標題。 在某些時點上,執行個體的數目將會突然下降。 這表示記憶體管理員已歸還一些物件的記憶體。
注意事項 如果已經按了 10 次以上,而 CDemo 執行個體數目沒有減少,您可能需要調整程式碼,讓它可以使用更多的記憶體。關閉表單返回開發環境,然後將 for 迴圈的重複次數增加到 10000,然後再次執行專案。
重複步驟 3。 這次,在記憶體管理員終結更多的物件之前,您將可執行地更久。
其實,您每重複步驟 3 一次,就可能在記憶體管理員介入之前分配更多的 CDemo 物件。 這是因為愈來愈多的 Visual Studio 被調換,留下更多空間給 CDemo 的執行個體使用。
關閉表單以返回開發環境。