全文在《程序员》杂志第11期,商业站点如果转载请事先和我或者杂志社联系,这里贴出的是当时撰写过程中的原文,在文章的最后,我保留了当时的初稿,仅仅代表个人观点
本来我是打算写一篇文章来比较C++/CLI和C#的语言特性,为此我认真阅读了一些C++/CLI相关的文章和部分C++/CLI语言规范文本,结果是让我感到沮丧。我原本对C++/CLI语言的热情,被其远远超出我原本想象的复杂性给浇灭了一大半。
编辑部里有一个很好的风气,就是对于一些问题在理解上有不同看法的时候,我们都会拿出来讨论。孟岩的C和C++功底比较扎实,我则对于C#较为熟悉。我们没有更多的讨论C#的泛型和匿名函数等等相关的特性,而是集中在托管代码和非托管代码的交互上,我想这是C++/CLI的独特优势,也是传统C++程序员关注的重点。而恰恰是那次讨论让我完全改变了看法。对于pin_ptr和interior_ptr,我们还无法透彻了解其背后的用意,比如pin_ptr在托管堆中如何指向固定对象,如何防止移动对象,在此技术上托管堆的垃圾回收如何进行,interior_ptr和pin_ptr的关系如何等等。网络上相关的文章都是相对泛泛的介绍C++/CLI带来的激动人心的特性,对于这些方面的剖析,似乎没有见到。虽然不知者不为罪,但是不知道却胡说就是一种罪过了。显然,我们所了解的内容还不足以让我有资格去评判两个语言的优劣。在放弃当初的想法之后,我下面的文字更多的是从个人的观点去阐述对于这两个语言的看法。
C++/CLI会抢占C#在.NET中的地位吗?我的观点:不会。正如Stan Lippman所言的,每一种语言都有自己的定位。C#作为一个没有任何历史包袱的语言,其设计的重点是开发效率和语言威力的平衡。从目前来说,C#是.NET语言家族中最均衡、适用面最广的语言,并且在VS.NET中提供了最好的IDE支持。在C# 2.0版本中加入的泛型、匿名函数和匿名内部类,也是从开发的角度去考虑的。传统C++适合做系统层面上的开发,但是在开发效率方面劣势明显。Managed C++在这个方面没有做太多的改进,相反加入的一些语法规则让许多开发人员接受不了。虽然C++/CLI在开发者体验方面已经做了大幅度的改进,从而使开发人员能够更加快速的进行应用开发,也提供了更加优雅的代码,但是C++天然的复杂性让其在业务应用范畴捉襟见肘,依旧无法替代C#在整个.NET开发语言中的地位。这是两个针对不同定位设计的语言,因此也是在不同的领域内发挥自己的特长。
C++/CLI对于.NET意味着什么?我的观点:大大拓展.NET平台的威力。当年的Managed C++只是完成了一个使命:保证现有的代码迁移到.NET平台上来。在其他方面因为其设计上过于保守,不但要完成自己的使命,也希望保持和ISO C++的高度兼容。这两个方面的顾忌让设计者缩手缩脚。从某种意义来说,正是因为对于Bjarne Stroustrup或者说ISO C++的虔诚造成了Managed C++在语言革新方面的扭曲。而到了C++/CLI时代,这一切将不复存在,Stan Lippman和Herb Sutter主导设计的C++除了保持和C++的兼容之外,同时引入了CLI,使开发人员能够以一种更加自然流畅的方式去编写代码,从而找回了在.NET平台中应有的位置。按照C++/CLI设计组的说法,C++/CLI将成为.NET之上最强大、最底层的语言——其能力甚至超越MSIL本身。优雅的语法,强大的功能,极限的效率,自然能够吸引更多传统C/C++程序员投入C++/CLI的怀抱。同时,C++/CLI对于.NET CLR提供了更加灵活的控制方式,也为开发人员掌握和扩展.NET的能力提供了前所未有的强大武器。这还这是一个开始,据Stan Lippman说,一些更具震撼性的思想将融入C++/CLI的下一个版本中,我只举一个例子就可以启发大家的遐想:下一版的C++/CLI,可以在CLR托管堆之外,于本地堆之中建立新的托管堆,将托管对象分配在本地堆中。
C++/CLI对于C#开发人员的诱惑在于何处?我的观点:配合C#拓展其功能。一些从C++转到C#的开发人员应该会有些抱怨,在日常的业务应用开发中,C#是最合适不过的语言,但是在于某些方面比如需要密集运算、特殊算法逻辑方面并没有展现出太大的优势,习惯于使用指针去解决的C++开发人员这个时候就认为C#是一个比较笨拙的设计,虽然C#也通过unsafe关键字提供了部分指针的支持,但是在一些对象操作方面,远远不如C++那样的随心所欲。C++/CLI为C#开发人员提供了一格新的选择:利用C++/CLI去实现部分的高性能部分,使用C#实现整体业务。这样的配合和使用VC写组件VB写应用逻辑的配合比较接近,有一点不同的就是所有的应用是完整基于.NET Framework,其跨度,较之当年的VB与VC,明显小许多。
综述如上的观点,C++/CLI的推出只是填补了.NET开发领域内的一块空白,对于C#不会造成本质的冲击,同时其大大拓展了平台的威力,相对于C#开发人员而言,提供了一个更加“高级实现”的可能。
如下为当时草稿,后来全部删除了,仅供参考
从我学习计算机的一开始我就不曾喜欢过微软在C++方面的实现,包括那个无所不能的MFC,因为一些费解的宏和一些提示不可以删除的注释代码让我觉得有点丑陋,至少在代码方面不如Pascal或者Java那样的简洁而优雅,加之职业方面更多的是侧重于业务的实现,因此我更多的是使用VB或者Java这样的语言去实现我想实现的东西,对于底层的Windows开发,我选择了逃避。当然后来的C#和VB.NET成为我新的选择又是另外一个故事了,在Visual Studio .NET 2003之前的版本,对于.NET家族里头的C++,我总是有一种莫明的感觉,总是有点“私生子”的错觉,就是怎么看就怎么不舒服,而2004年9月17日Stan Lippman和言谈就确实证明了我当初的看法,在Managed C++上,设计人员过于保守的思想造就了一个“怪物”。Stan Lippman认为他们对于Bjarne Stroustrup或者说ISO C++的虔诚在无意中去伤害了很多人,一个方面既要保持ISO C++的高度兼容,一个方面需要设计出一个能够将现有代码移植到.NET平台来的语言,这两个顾忌让他们畏首畏脚,从而造成语言革新的扭曲。相信大多开发人员对于Managed C++的理解是C++语言一个比较蹩脚的扩展,以至于在社区中有人提出了“.NET平台上C++走向何方”的论调,因为在他们的眼里,Managed C++那样的设计更多的是将它自己一点一点的推入地狱。
Stan Lippman是一个很慈祥的老人,也是一个非常有意思的家伙,这次来中国似乎就是要告诉大家“嗨,C++回来了”。是的,C++/CLI的推出会让更多人拾起渐渐丢失的信心,然后重回C++怀抱。Stan Lippman和Herb Sutter时代的C++除了保持和C++的兼容意外,同时引入了CLI,使开发人员能够以一种更加自然流畅的方式去编写代码,从而找回了在.NET平台中应有的位置。
要如何去评价C#呢?作为和Java一样没有历史包袱的语言,在语法机制方面对于流行的应用开发几乎无可挑剔,从语法的角度而言,这是我最喜欢的语言,因为其优雅和开发方面的高效,在2.0中引入了泛型(Generic)、匿名函数、局部类和迭代器,我想一切的出发点是和主流的软件开发方法学靠拢,更加关注的是开发效率方面的提升。既然不存在向下兼容的历史包袱,Anders主笔的C#在很大程度上来说可以认为是对于开发体验最好的语言,同时在IDE方面的支持也远远超过C++/CLI。
描述
C++/CLI
C#
创建引用类型的对象
ReferenceType^ h = gcnew ReferenceType;
ReferenceType h = new ReferenceType();
创建值类型的对象
ValueType v(3, 4);
ValueType v = new ValueType(3, 4);
引用类型在堆栈上
ReferenceType h;
N/A
调用Dispose 方法
ReferenceType^ h = gcnew ReferenceType;
delete h;
ReferenceType h = new ReferenceType();
((IDisposable)h).Dispose();
实现Dispose方法
~TypeName() {}
void IDisposable.Dispose() {}
实现Finalize 方法
!TypeName() {}
~TypeName() {}
装箱(Boxing)
int^ h = 123;
object h = 123;
拆箱(Unboxing)
int^ hi = 123;
int c = *hi;
object h = 123;
int i = (int) h;
定义引用类型
ref class ReferenceType {};
ref struct ReferenceType {};
class ReferenceType {}
定义值类型
value class ValueType {};
value struct ValueType {};
struct ValueType {}
使用属性
h.Prop = 123;
int v = h.Prop;
h.Prop = 123;
int v = h.Prop;
定义属性
property String^ Name
{
String^ get()
{
return m_value;
}
void set(String^ value)
{
m_value = value;
}
}
string Name
{
get
{
return m_name;
}
set
{
m_name = value;
}
}
本文地址:http://com.8s8s.com/it/it25888.htm