.Net運行環境是語言無關的:開發者可以用不同的.Net語言編寫組件。而且在實際開發中往往就是這樣的。你創建的程序集必須是與公共語言系統(CLS)是兼容的,這樣才能保證其它的開發人員可以用其它的語言來使用你的組件。
CLS的兼容至少在公共命名上要與互用性靠近。CLS規范是一個所有語言都必須支持的最小操作子集。創建一個CLS兼容的程序集,就是說你創建的程序集的公共接口必須受CLS規范的限制。這樣其它任何滿足CLS規范的語言都可以使用這個組件。然而,這並不是說你的整個程序都要與CLS的C#語言子集相兼容。
為了創建CLS兼容的程序集,你必須遵從兩個規則:首先,所以參數以及從公共的和受保護的成員上反回的值都必須是與CLS兼容的。其次,其它不與CLS兼容的公共或者受保護成員必須存在CLS兼容的同意對象。
第一個規則很容易實現:你可以讓編譯來強制完成。添加一個CLSCompliant 特性到程序集上就行了:
[ assembly: CLSCompliant( true ) ]
編譯器會強制整個程序集都是CLS兼容的。如果你編寫了一個公共方法或者屬性,它使用了一個與CLS不兼容的結構,那麼編譯器會認為這是錯誤的。這非常不錯,因為它讓CLS兼容成了一個簡單的任務。在打開與CLS兼容性後,下面兩個定義將不能通過編譯,因為無符號整型不與CLS兼容:
// Not CLS Compliant, returns unsigned int:
public UInt32 Foo( )
{
return _foo;
}
// Not CLS compliant, parameter is an unsigned int.
public void Foo2( UInt32 parm )
{
}
記住,創建與CLS兼容的程序集時,只對那些可以在當前程序集外面可以訪問的內容有效。Foo 和Foo2 在定義為公共或者受保護時,會因與CSL不兼容而產生錯誤。然而如果Foo 和Foo2是內部的,或者是私有的,那麼它們就不會被包含在要與CLS兼容的程序集中;CLS兼容接口只有在把內容向外部暴露時才是必須的。
那麼屬性又會怎樣呢?它們與CLS是兼容的嗎?
public MyClass TheProperty
{
get { return _myClassVar; }
set { _myClassVar = value; }
}
這要視情況而定,如果MyClass是CLS兼容的,而且表明了它是與CLS兼容的,那麼這個屬性也是與CLS兼容的。相反,如果MyClass沒有標記為與CLS兼容,那麼屬性也是與CLS不兼容的。就意味著前面的TheProperty屬性只有在MyClass是在與CLS兼容的程序集中是,它才是與CLS兼容的。
如果你的公共的或者受保護的接口與CLS是不兼容的,那麼你就不能編譯成CLS兼容的程序集。作為一個組件的設計者,如果你沒有給程序集標記為CLS兼容的,那麼對於你的用戶來說,就很難創建與CLS兼容的程序集了。他們必須隱藏你的類型,然後在CLS兼容中進行封裝處理。確實,這樣可以完成任務,但對於那些使用組件的程序員來說不是一個好方法。最好還是你來努力完成所有的工作,讓程序與CLS兼容:對於用戶為說,這是可以讓他們的程序與CLS兼容的最簡單的方法。