VS.NET 引入雙底線關鍵字 (__gc, __property 等) 作為擴展,雖避免與標準編譯器衝突,但導致語法不自然、無法完整採用。C++/CLI 在 VS 2005 中徹底移除雙底線,提供一流自然語言體驗。
// 舊語法 (VS.NET)
public __gc class Foo {
// 數百行程式碼
__property String* get_Text();
// 數百行程式碼
__property void set_Text(String*);
// 數百行程式碼
};
新語法將屬性整合為單一語法單元,清晰表達意圖:
// 新語法 (C++/CLI)
ref class Foo {
property String^ Text {
String^ get() { ... }
void set(String^ value) { ... }
}
};
C++ 開發者偏好確定性解構 (RAII)。傳統 .NET 垃圾回收非確定性,Dispose() 模式繁瑣。C++/CLI 允許在堆疊上宣告托管物件,享有確定性生命週期:
// 原生 C++ 堆疊物件
{ Foo f; /* 超出作用域自動解構 */ }
// C++/CLI 托管物件堆疊語義
{ Foo^ f = gcnew Foo(); /* 實際在托管堆,但編譯器注入智慧指標 */ }
{ Foo f; /* 直接宣告,超出作用域自動呼叫 Dispose */ }
此機制讓開發者可將托管物件作為成員變量嵌入原生類別,擁有完整 C++ 生命週期控制,而非被動等待 GC。
~Foo():實作 IDisposable::Dispose,釋放托管與非托管資源,抑制完成項。!Foo():實作 Object::Finalize,僅釋放非托管資源,作為安全網。~ 為位元 NOT,! 為邏輯 NOT,暗示與建構函式對立。刪除控制代碼 (delete h) 會呼叫 Dispose,記憶體回收交給 GC。
舊語法 * 語義依賴類別宣告 (__gc),極易混淆。新語法:
Foo* pf = new Foo(); (CRT 堆,需手動 delete,支援指標運算)Foo^ hf = gcnew Foo(); (托管堆,GC 管理,自動更新位址,可重繫結,支援 */-> 解參考,不支援指標運算)生命週期宣告從類別定義移至實例宣告,更直觀。
ref class 為關鍵字組合,非單一關鍵字,避免與變數名 ref 衝突。同理 value class、interface class、enum class。ref class 為托管類別,設計給 GC 管理,但可用堆疊語義宣告實例。
ref class R {
property int Size {
int get() { return m_Size; }
void set(int val) { m_Size = val; }
}
private: int m_Size;
};
R r;
r.Size = 42; // 自然語法
property 為上下文關鍵字,僅在類別定義中具特殊含義,不汙染一般識別符空間。編譯器自動產生 get_Size/set_Size 及中繼資料。