符合CLS(Common Language Subsystem)标准的程序集可以被其他跑在CLR的语言公用,这是.NET的一个引以为傲的特性,这样你用一种语言编写的程序集就可以被其他在CLR同样支持的程序调用了。要实现这个效果,要求更多的时间来设计构建你的程序集。主要要求两点:
- 所有public和protected的成员方法的参数和返回值必须是符合CLS标准的。你只需在你的程序集属性上添加如下属性声明即可:
[assembly: System.CLSCompliant(true)]
这样声明后,你的程序集在编译时就会检查你里边的代码是否是符合CLS标准的。例如下面的两段代码由于UInt32类型并不支持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标准的public和protected成员方法,都应有符合CLS标准的方法来代替。
如并非所有的语言都支持的运算符重载,你就需要在代码中添加该运算符相等处理逻辑的静态方法,如下代码所示:
// Overloaded Addition operator, preferred C# syntax:
public static Foo operator +(Foo left, Foo right)
{
// Use the same implementation as the Add method:
return Foo.Add(left, right);//使用了静态方法中的逻辑,这样便于维护
}
// Static function, desirable for some languages:
public static Foo Add(Foo left, Foo right)
{
return new Foo(left.Bar + right.Bar);
}
注意:在继承时对于CLS标准的影响,下面的代码中的BasEventArgs类继承自符合CLS标准的类型EventArgs,但其内部有一个公有属性ErrorCode,其类型为 UInt32,不被CLS标准支持,所以当使用该类型(BadEventArgs)来做参数的方法或委托就不是符合CLS标准的了,如下代码所示:
public class BadEventArgs : EventArgs
{
public UInt32 ErrorCode;
}
// Hiding the non-compliant event argument:
public delegate void MyEventHandler(object sender, EventArgs args );
public event MyEventHandler OnStuffHappens;
// Code to raise Event:
BadEventArgs arg = new BadEventArgs();
arg.ErrorCode = 24;
// Interface is legal, runtime type is not:
OnStuffHappens(this, arg);//这里在编译时不出错,但在运行时就不符合CLS标准规范了
再来看一个例子:
public interface IFoo2
{
// Non-CLS compliant, Unsigned int
void DoStuff(UInt32 arg1, string arg2);//不符合CLS规范的方法
}
public class MyClass2 : IFoo2
{
// explicit interface implementation.
// DoStuff() is not part of MyClass's public interface
void IFoo2.DoStuff(UInt32 arg1, string arg2)
{
// content elided.
}
}
上面的代码定义了一个不符合CLS标准的方法IFoo2,其方法DoStuff(UInt32 arg1, string arg2)由于参数类型的原因,不符合规范。而MyClass2继承自该接口,并显示的实现了该方法。但对于MyClass2来说其还是符合CLS规范的,因为DoStuff方法的调用,是属于IFoo2的。也就是说在使用该类型的对象的DoStuff方法时,你需要先把该对象显示的转换为IFoo2的对象才能使用。也就是你只能这么调用DoStuff方法:
MyClass2 myClass2 = new MyClass2();
(myClass2 as IFoo2).DoStuff(1, "hello compliance");
总结:实现CLS标准的程序集可以被其他运行在CLR平台的语言调用,但是要付出一点设计和构建的努力。当然,也不是说你所有的程序集都要为了这个目标去构建,你只需在需要多语言交互的接口使用符合CLS标准来构建就可以了,把转换封装到接口中,这样产出比还是很可以接受的。 :)