傳統 COM 元件開發門檻高,.NET 與 C# 讓元件開發變得平易近人。C# 被稱為「面向元件的語言」,原生支援屬性、事件、介面、版本控制等元件級特性。
namespace ComponentCS {
public class StringComponent {
private string[] stringsSet;
// 唯讀屬性
public int StringLength => stringsSet.Length;
// 方法
public void Modify(int index, string value) {
if (index < 0 || index >= stringsSet.Length)
throw new IndexOutOfRangeException();
stringsSet[index] = value;
OnModify();
}
// 建構函式
public StringComponent() {
stringsSet = new[] { "C# String 0", "C# String 1", "C# String 2", "C# String 3" };
}
public string GetString(int index) {
if (index < 0 || index >= stringsSet.Length)
throw new IndexOutOfRangeException();
return stringsSet[index];
}
}
}
namespace Outer { namespace Inner { class C {} } } → Outer.Inner.Cnamespace A {} namespace B {}| 特性 | 欄位 | 屬性 |
|---|---|---|
| 語法 | public int Age; | public int Age { get; set; } |
| 封裝 | 直接存取 | 透過存取子控制邏輯 |
| 唯讀 | readonly | 僅 get |
| 傳遞 | 可 ref/out | 不可 ref/out |
| 介面 | 不可定義 | 可定義 |
原則:公開成員優先用屬性,保留未來加入驗證、通知、延遲載入的彈性。
this(...)new 運算子配置記憶體後、傳回參考前throw new IndexOutOfRangeException();
public class MyApplicationException : ApplicationException {
public string DetailMessage { get; }
public MyApplicationException(string msg) => DetailMessage = msg;
}
// 使用
public string GetString(int index) {
try {
if (index < 0 || index >= stringsSet.Length)
throw new MyApplicationException("索引超出範圍");
} catch (MyApplicationException ex) {
Console.WriteLine(ex.DetailMessage);
} catch (Exception ex) {
Console.WriteLine(ex.Message);
}
return stringsSet[index];
}
public event EventHandler Modified;
private void OnModify() {
Modified?.Invoke(this, EventArgs.Empty); // C# 6.0 null 條件運算子
// 舊寫法:
// var handler = Modified;
// if (handler != null) handler(this, EventArgs.Empty);
}
var component = new StringComponent();
component.Modified += Component_Modified; // 訂閱
component.Modified -= Component_Modified; // 取消訂閱
private void Component_Modified(object sender, EventArgs e) {
Console.WriteLine("資料已變更");
}
using System;
namespace ComponentCS {
public class StringComponent {
private string[] stringsSet;
public event EventHandler Modified;
public int StringLength => stringsSet.Length;
public void Modify(int index, string value) {
if (index < 0 || index >= stringsSet.Length)
throw new IndexOutOfRangeException();
stringsSet[index] = value;
OnModify();
}
private void OnModify() => Modified?.Invoke(this, EventArgs.Empty);
public StringComponent() {
stringsSet = new[] { "C# String 0", "C# String 1", "C# String 2", "C# String 3" };
}
public string GetString(int index) {
if (index < 0 || index >= stringsSet.Length)
throw new IndexOutOfRangeException();
return stringsSet[index];
}
}
}
csc.exe /target:library /debug+ /out:StringComponent.dll StringComponent.cs
/target:library:產生 DLL 而非 EXE/debug+:產生 .pdb 方便偵錯/out:指定輸出檔名優點:原始碼保護、IL 已編譯載入快、版本管理、跨語言互通(VB.NET、F# 皆可引用)。
sn -k key.snk + /keyfile:key.snk → GAC 部署、版本綁定[assembly: AssemblyVersion("1.0.0.0")]PackageReference十分鐘建立基礎元件,一生精進元件架構。C# 賦予開發者強大的元件建構能力,關鍵在於設計意圖與工程紀律的結合。