.NET 運行時支援多語言開發。為讓組件被所有 .NET 語言使用,公開介面必須符合共同語言規範 (CLS)。CLS 定義所有語言必須支援的最小功能子集。
[assembly: CLSCompliant(true)]
編譯器將強制檢查整個組件。例如,UInt32 不符合 CLS,以下程式碼將報錯:
// 錯誤:回傳型別非 CLS 合規
public UInt32 Foo() { return _foo; }
// 錯誤:參數型別非 CLS 合規
public void Foo2(UInt32 parm) { }
若成員為 internal 或 private,不受此限制(不屬公開介面)。
非所有語言支援運算子多載。CLS 定義對應方法名(如 op_Addition 對應 +)。建議同時提供靜態方法:
public static Foo operator+(Foo left, Foo right) => Foo.Add(left, right);
public static Foo Add(Foo left, Foo right) => new Foo(left.Bar + right.Bar);
internal class BadEventArgs : EventArgs { internal UInt32 ErrorCode; }
// 介面宣告用基類 EventArgs(合規),但實際傳遞 BadEventArgs(不合規)
public delegate void MyEventHandler(object sender, EventArgs args);
OnStuffHappens(this, new BadEventArgs { ErrorCode = 24 }); // 非 CLS 語言無法使用
解決:事件參數型別必須實際為 CLS 合規型別。
public class MyClass : IFoo2 // IFoo2 含 UInt32 參數
{
void IFoo2.DoStuff(UInt32 arg1, string arg2) { ... } // 隱藏於公開介面外
}
MyClass 公開介面保持 CLS 合規,需使用非合規介面者須強制轉型。
CLS 合規不要求所有代碼合規,僅公開介面需合規。編譯器協助強制檢查,稍加注意即可建立跨語言通用組件。