.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兼容的最简单的方法。