微软在C /CLI中选择地址集合模式来处理托管堆上的值类型。
int ival = 1024;
int^ boxedi = ival;
array<int>^ ia = gcnew array<int>{1,1,2,3,5,8};
interior_ptr<int> begin = &ia[0];
value struct smallInt { int m_ival; ... } si;
pin_ptr<int> ppi = &si.m_ival;
典型地C /CLI研发人员是个复杂的系统程式员,承担着提供下层内部构造和有组织的应用程式的任务,而这些恰恰是未来商业发展的基础。C /CLI研发人员必须兼顾可测量性和可执行性,所以必须在系统的高度级上来看待CLI下层结构。CLI细节水平反映了研发人员的脸色。
复杂性本身并不代表对质量的否定,人类比单细胞细菌复杂的多,这当然不是一件坏事,然而,当表达一个简单的概念变的复杂化后,这常常被认为是一件坏事。在C /CLI中,CLI研发团队已试着提供一种精巧的方法来表达方式一个复杂的事情。
额外增加的功能
第三个设计方面是特定功能性的语言层,他远远超过CLI所提供的直接支持,虽然这可能需要在语言层支持和CLI底层执行模式间建立一个映射。但在某些情况下,这恰恰是不可能的,因为语言无法调节CLI的行为。这种情况的例子就是在基类的构造及析构函数中定义虚函数。根据ISO-C 在这种情况下的语言学,需要用每一个基类的构造和虚构函数重新配置虚拟表,而这是不可能的,因为虚拟表句柄是实时管理的,而不是某一个语言来管理。
所以,这个设计方面是在完美性和可行性之间的妥协产物,C /CLI提供的额外功能主要表现在三个方面:
1、获取资源的一种形式是对于引用类型的初始化,此外,提供一种自动化工具,用于占用较少资源、所谓的可确定性自动消亡的垃圾收集类型对象。
2、一种深度拷贝形式的语法和C 拷贝构造函数和拷贝分配操作符相一致,但其并不适用和值类型。
3、除了最初的一般性CLI机制外,更有对于CTS类型的C 模板直接支持。这些是我第一篇文章中讨论的主题。此外,还提供了针对CLI类型的可校验STL版本。
让我们来看一个简单的例子,一个确定性消亡问题。在垃圾搜集器重新声明一块和对象相关联的内存之前,一个相关的消亡方法,假如存在的话,将被调用。您能够认为这种方法是终极析构函数,因为他和对象的程式生命期无关。这就叫做终结。终结函数是否调用连同什么时间调用都没有明确规定,这就是垃圾收集器的非确定性终结。
在动态内存管理的情况下,非确定性终结工作很好,当可用内存变的越来越少时,垃圾收集器介入并开始着手解决问题。然而,非决定性终结也有工作不好的时候,当一个对象维护一个重要资源,例如一个数据库连接、锁定某些类别、或可能是本地的堆内存。在这种情况下,只要是无需,应立即释放资源。现在CLI所支持的解决问题的方法是,对于一个类通过执行IDisposable接口提供的Dispose方法释放资源。这里的问题是执行Dispose方法需要一个清楚的声明,所以他也就不可能存在调用。
最基本的C 中的设计模式是上述的通过初始化来获取资源,这意味着类使用构造函数来获取资源,相反,类使用析构函数来释放资源。这些行为由类对象在生存期内自动管理。
下面是引用类释放资源时所做的顺序动作:
1、 首先使用析构函数来封装任何和释放类有关的资源时所必须的代码;
2、 析构函数自动调用后,结束类对象的生命期。
对于引用类型来说,CLI没有类析构函数的概念,所以析构函数不得不映射为在底层执行的其他代码。此时,在内部,编译器执行以下操作:
1、 类让其基类列表继承自IDisposable接口;
2、 析构函数转换成IDisposable的Dispose方法。
以上实现了目标的一半,一种实现析构造函数自动调用的方法仍然需要,对于引用类型,一种特别的基于栈的符号得到支持,也就是说,一个对象的生命期和他的声明范围有关。在内部,编译器将符号转换为在托管堆上分配引用对象。随着作用域的终结,编译器插入一个Dispose方法-用户定义的析构函数。和对象有关的内存的收回在垃圾收集器的控制下得到执行。
C /CLI并不是将C 拓展到一个托管的世界,更确切的说,他代表一个完全综合的范例,某种程度上就象当初将泛编程模式和多重继承综合进该语言相同。我认为C /CLI研发小组做了一项很卓有成效的工作。
小结
C /CLI代表托管和本地编程的结合。在反复过程中,这种综合已通过源级相对单独但又相互平等地组件和二进制元素得到了完成,包括混合模式(本地和CTS类型的源级混合,更有一个本地及CLI对象文档的二进制混合),纯模式(本地和CTS类型的源代码级混合,任何的都被编译为CLI对象文档),本地分类(能够通过一个特定的打包类来保持CTS类型),和CTS分类(能够保持本地类型为指针)。
当然,C /CLI研发人员也能够单独使用CLI类型来编程,并通过这种方式来提供伺服状态下的可校验代码,例如能够作为SQL Server2005的一个SQL存储过程。
现在,还是回到这个问题上来,什么是C /CLI?他是进行.NET编程模式的最好切入点。对于C /CLI,有一个来自C 的迁移路径,他不但包含C 的底层基础,而且也需要C 编程经验,对于这些,我感到很满意。




