.NET,你忘记了么(一)—— 遵从CLS

首先,让我们来简单地看下什么叫做CLS。

鉴于个人的英文水平,我还是先给出CLS的英文解释,然后我再翻译:

The CLS is a specification that defines the rules to support language integration. This is done in such a way, that programs written in any language (.NET compliant) can interoperate with one another. This also can take full advantage of inheritance, polymorphism, exceptions, and other features.

CLS定义了支持语言继承的规范,他使我们所写的程序可以于任何一门.NET所兼容的语言交互,这使我们也可以充分利用继承,多态,异常以及其他一些特点的优势。

其实简化了说,CLS就是定义了个门语言的子集,从而去保证语言的互操作性。

因此,为了语言之间的互操作,我们应该使我们的程序遵从CLS。

我们看一下系统的层次,系统下应该是程序集,程序集下就是类(或结构体等)。那么我们为了保证语言的互操作性,就应该保证程序集对外的部分都遵从CLS。

这点很容易保证:

当我们新建一个程序集的时候,有一个文件叫做:AssemblyInfo.cs:

[assembly: AssemblyTitle("ClassLibrary1")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("微软中国")]
[assembly: AssemblyProduct("ClassLibrary1")]
[assembly: AssemblyCopyright("Copyright © 微软中国 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// 将 ComVisible 设置为 false 使此程序集中的类型
// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
// 则将该类型上的 ComVisible 属性设置为 true。
[assembly: ComVisible(false)]

// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("694543e8-4c7f-4952-9e98-7282ecff1c15")]

// 程序集的版本信息由下面四个值组成:
//
//      主版本
//      次版本 
//      内部版本号
//      修订号
//
// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值,
// 方法是按如下所示使用“*”:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
毫无疑问,这里记录的都是当前程序集的信息,那么我们只需要在里面加上一行代码:
[assembly:System.CLSCompliant(true)]

这样程序就保证了整个程序集满足CLS规范。

当我们写一段不满足CLS的程序时:

namespace ClassLibrary1
{
    public class People
    {
        private string name;
        private uint age;   //uint不满足CLS
        public uint Age
        {
            get
            {
                return age;
            }
        }
        public People(string name)
        {
            this.name = name;
        }
    }
}

当我们生成程序集的时候,报出了这样的警告:

image

当然,我再对这个做一些附加的解释,希望不是画蛇添足:

我们都知道,一个程序集存在一些对外的接口,其他的程序集只是与这些对外的接口进行交互,也就是说只要对外的接口满足CLS,这个程序集就可以进行与其他语言的互操作了:

看一个例子,当我们把上述的class People设置为默认的访问修饰符internal时:

class People
{
    private string name;
    private uint age;   //uint不满足CLS
    public uint Age
    {
        get
        {
            return age;
        }
    }
    public People(string name)
    {
        this.name = name;
    }
}

这个时候,当我生成程序集的时候,并不会报CLS不兼容的错误:

image

因此,我不想再去说哪些类需要满足CLS。我们只需要记住,如果你写的某个类,或者变量,方法,在程序集可以访问到,那么这个类,方法,变量就需要满足CLS。

当然,有这样一种情况,就是说使用了不满足CLS的方法,变量等会极大提高整个程序的可读性,那么我们就该为这个方法,或者变量等实现一个与其等义的方法等,于是,如果访问该程序集的是同一语言,那么便访问该方法,否则便访问替代方法。

另外,有一种能力叫做取舍。我们不可能做出一个十全十美的项目,人力不允许,物力不允许,精力也不允许,因此,我们必须要放弃一些东西。当我们这个项目基本不太可能与其他语言进行交互时,那么我就没有必要将精力去集中在项目程序集是否满足于CLS上。

当然,如果我们有时间,那么抽出些时间去搞定语言的互操作,还是利大于弊的!

posted @ 2009-02-18 17:22  飞林沙  阅读(3783)  评论(11编辑  收藏