Effective C#原则30:选择与CLS兼容的程序集

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

时间: 2024-12-31 12:47:52

Effective C#原则30:选择与CLS兼容的程序集的相关文章

Effective C#原则33:限制类型的访问

并不是所有的人都须要知道所有的事.也不是所有的类型须要是公共的.对于每个类型,在满足功能的情况下,应该尽可能的限制访问级别.而且这些访问级别往往比你想像的要少得多.在一个私有类型上,所有的用户都可以通过一个公共的接口来访问这个接口所定义的功能. 让我们回到最根本的情况上来:强大的工具和懒惰的开发人员.VS.net对于他们来说是一个伟大的高产工具.我用VS.net或者C# Builder轻松的开发我所有的项目,因为它让我更快的完成任务.其中一个加强的高产工具就是让你只用点两下按钮,一个类就创建了,

Effective C#原则45:选择强异常来保护程序

当你抛出异常时,你就在应用程序中引入了一个中断事件.而且危机到程序 的控制流程.使得期望的行为不能发生.更糟糕的是,你还要把清理工作留给最 终写代码捕获了异常的程序员.而当一个异常发生时,如果你可以从你所管理的 程序状态中直接捕获,那么你还可以采取一些有效的方法.谢天谢地,C#社区不 须要创建自己的异常安全策略,C++社区里的人已经为我们完成了所有的艰巨的 工作.以Tom Cargill的文章开头:"异常处理:一种错误的安全感觉, " 而且Herb Sutter,Scott Meyer

Effective C#原则40:根据需求选择集合

"哪种集合是最好的?"答案是:"视情况而定." 不同的集合有不同的性能,而且在不同的行为上有不同的优化..Net框架支持很 多类似的集合:链表,数组,队列,栈,以及其它的一些集合.C#支持多维的数 组,它的性能与一维的数组和锯齿数组都有所不同..Net框架同样包含了很多特 殊的集合,在你创建你自己的集合类之前,请仔细参阅这些集合.你可以发现很 多集合很快,因为所有的集合都实现了ICollection接口.在说明文档中列出了 所有实现了ICollection接口的集合

Effective C#原则35:选择重写函数而不是使用事件句柄

很多.Net类提供了两种不同的方法来控制一些系统的事件.那就是,要么添 加一个事件句柄:要么重写基类的虚函数.为什么要提供两个方法来完成同样的 事情呢?其实很简单,那就是因为不同的情况下要调用为的方法.在派生类的内 部,你应该总是重写虚函数.而对于你的用户,则应该限制他们只使用句柄来响 应一些不相关的对象上的事件. 例如你很了一个很不错的Windows应用程 序,它要响应鼠标点下的事件.在你的窗体类中,你可以选择重写OnMouseDown ()方法: public class MyForm :

Effective C#原则47:选择安全的代码

.Net运行时已经设计好了,一些怀有恶意的代码不能渗透到远程计算机上并 执行.目前一些分部式系统依懒于从远程机器上下载和执行代码.如果你可以通 过Internet或者以太网来发布你的软件,或者直接从web上运行,但你须要明白 CRL在你的程序集中的一些限制.如果CLR不是完全相信一个程序集,它会限制一 些的行为.这些调用代码要有访问安全认证(CAS).从另一方面来说,CLR强制要 求基于角色的安全认证,这样这些代码才能或者不能在基于一个特殊的角色帐号 下运行. 安全违例是运行时条件,编译器不能强

Effective C#原则41:选择DataSet而不是自定义的数据结构

因为两个原则,把DataSet的名声搞的不好.首先就是使用XML序列化的 DataSet与其它的非.Net代码进行交互时不方便.如果在Web服务的API中使用 DataSet时,在与其它没有使用.Net框架的系统进行交互时会相当困难.其次, 它是一个很一般的容器.你可以通过欺骗.Net框架里的一些安全类型来错误 DataSet.但在现代软件系统中,DataSet还可以解决很多常规的问题.如果你明 白它的优势,避免它的缺点,你就可以扩展这个类型了. DataSet类设计 出来是为了离线使用一些存储

Effective C#原则32:选择小而内聚的程序集

这一原则实际应该取这个名字:"应该创建大小合理而且包含少量公共 类型的程序集".但这太沉长了,所以就以我认为最常见的错误来命名: 开发人员总是把所有的东西,除了厨房里水沟以外(译注:夸张说法,kitchen sink可能是个口语词,没能查到是什么意思,所以就直译了.),都放到一个程 序集.这不利于重用其中的组件,也不利于系统中小部份的更新.很多以二进制 组件形式存在的小程序集可以让这些都变得简单. 然而这个标题对于程 序集的内聚来说也很醒目的.程序集的内聚性是指概念单元到单个组件的职责

Effective C#原则31:选择小而简单的函数

做为一个有经验的程序员,不管你在使用C#以前是习惯用什么语言的,我们 综合了几个可以让你开发出有效代码的实际方法.有些时候,我们在先前的环境 中所做的努力在.Net环境中却成了相反的.特别是在你试图手动去优化一些代码 时尤其突出.你的这些行为往往会阻止JIT编译器进行最有效的优化.你的以性 能为由的额外工作,实际上产生了更慢的代码.你最好还是以你最清楚的方法写 代码,其它的让JIT编译器来做.最常见的一个例子就是预先优化,你创建一个 很长很复杂的函数,本想用它来避免太多的函数调用,结果会导致很多

Effective C#原则24:选择申明式编程而不是命令式编程

与命令式编程相比,申明式编程可以用更简单,更清楚的方法来描述软件的 行为.申明式编程就是说用申明来定义程序的行为,而不是写一些指令.在C#里 ,也和其它大多数语言一样,你的大多数程序都是命令式的:在程序中写一个方 法来定义行为.在C#中,你在编程时使用特性就是申明式编程.你添加一个特性 到类,属性,数据成员,或者是方法上,然后.Net运行时就会为你添加一些行为 .这样申明的目的就是简单易用,而且易于阅读和维护. 让我们以一个 你已经使用过的例子开始.当你写你的第一个ASP.Net Web服务时,