C#:昨天,今天和明天-和 Anders Hejlsberg 座谈

来源:互联网 发布:寂静如歌 李健 知乎 编辑:程序博客网 时间:2024/04/29 09:50

 Anders Hejlsberg 在1996年加入微软,开始是Visual J++ 和 Windows Foundation Classes 的架构师。Hejlsberg 是目前微软杰出的工程师和C#语言的设计者,并在微软 .NET 框架中扮演了重要的角色。今天,他正在领导C#语言的开发工作。John Osborn,是O’Reilly 媒体公司的执行编辑,负责公司在.NET和其他微软开发者书籍的工作,最近和Hejlsberg碰面进行了下面广泛的会谈。

 

Osborn:我想我最好还是跳回到2000年我们上次聊天的地方。重新复习上次的对话,对我来说是很有趣的。那时,我们曾经被java痴迷,C#语言和java的对比当时也非常的多。

 

 

 

Hejlsberg:是这样的。

 

 

 

Osborn:从那是起五年过去了C#现在怎么样了你现在对语言有什么想法吗C#是微软唯一的工具吗是否在社区里有一个很宽的领域

 

 

 

Hejlsberg:是这样的。这几年发生了很多事情世界的发展看起来和当时非常不同特别是从一个竞争的观点来看。我们没有让.NET和java变得更新,更流行。因此,这里有很多比较可以做。我想在过去的五年里,C#已经成长起来了。今天,我们来说说C# 3.0 我们刚刚发布了 C# 2.0 ,在这之前是 1.0 和 1.1 的版本。

 

 

 

我们考虑跟踪研究从使用方式上看.NET看起来和java有着非常相似的应用。C#的应用更多一些。因此,相对于一个新语言,C#已经成长起来了。很显然,我非常高兴看到这种情况。在.NET和java平台上有着很多明显的不同。我的意思是首先.NET是windows的开发平台。这让你有了一个不同的商业策略。现在,你也知道,我们正在着手进行C#的标准化和. NET框架的核心工作。现在实际上已经有了C# 3.0 的一个标准版本了。ECMA-334 and ISO/IEC 23270]

 

 

 

这里有一点迷惑那些可以称为是3.0 那些则是2.0......

 

 

 

Osborn:这是我后面要问你的问题。

 

 

 

Hejlsberg:这些数字这有一点不行我们应该在某种程度上修改一些东西。但除此之外,已经有第三方独立的C#的实现了。这就是大家都知道的Mono。并且,并不是我们的私有策略。

 

 

 

同时我也想微软在过去的五年中从透明化社区参与开放程度等方面有了很大的转变。像我们现在和客户进行的对话和五年之前是非常非常不同的,和十年前相比更是天壤之别。你知道,整个行业,通过Blog和开放源代码,已经改变了很多,单个开发者参与的也和过去是不能比拟的。

 

 

 

C# 语言作为面向组建的语言

Osborn:当你在2000介绍C#语言的时候一个很厉害的武器是这是第一个面向组件的语言。在过去的五年中,这一点改变了吗?

 

 

 

Hejlsberg:当然变得更好的。可是C#仍然是有很多面向组件语言的特点。这带给我们属性,方法,事件和其他的开发者每天编程都会平到核心部分。很久以前,甚至最近,编程仍然是一个辅助工具,这些工具仍然倾向于这样一种编程模型:设计界面,在这上面放上组件,然后修改属性,并加上代码。

 

 

 

我总觉得属性事件方法是如此重要应该作为语言的一等公民来对待这就是我们在C#上所做的工作。老实说:我也听到了一些对属性的抱怨。这其实是个屁事,你明白我的意思吗?事实上,人们总是按照事实来想问题。

 

 

 

从常识上来看作为一等公民来看待的主意是我们经常做的是非常自然的。我们在LINQ中有很多方法来做一件事情,语言集成的查询,不是吗?因为我们都需要查询,那么不应该在编程语言中把这些查询符号作为很重要的事情对待吗?用声明的方法在一个更高的层次来表达一些事情比你写很多诸如for循环和if判断语句的来得更自然吧。

 

 

Osborn:

回到和语言相关的问题,我现在还是想说说LINQ。微软 Visual Stuido .NET 的产品经理 Tony Goodhew 在一次访谈中说过,微软的研究表明越来越多的人倾向于在编程中使用2种或者更多的语言来工作。好像现在有一种感觉,这就是语言只是 syntactic sugar 语法糖块。你选择某种语言是因为你对他最满意。

你认为现在有这种变化吗?我们以前没有过多谈过这方面的。

Hejlsberg:

好吧,的确没有谈过,但是语法是不是走到了尽头?我的意思是我们只是用 XML 文档来描述抽象语法树来表现你想做的,这也是一种语法,但是很显然,这对程序员来说并不怎么有用。因此,我认为编程语言在人们的脑海中占据这一个特别的位置,如果人们用语言说话是表达自己的一种方式,程序语言也和自然语言一样用来表达你自己的。

实际上,语法是编程语言的组成和表现形式,在很多方面,语法影响你如何思考你的程序,等等。因此,我认为语法很重要,非常重要。

Osborn:

那么从语法的角度来看,C#有什么特别的呢?你能给我们描述一下吗?

Hejlsberg:

好,我认为我们现在所说的面向组件类的特点是极为重要的。我们努力的做到没有其他的方法可以做这件事情。我们尝试发现语法间的协同,我的意思是:这很难用语言来精确的形容。那我们来看看语言级别集成的LINQ查询吧。这个可扩展的模型是:我们采用方法调用的方式来实现这一点。当你使用 where , orderby  和  select 语句来写查询语句的时候,我们把这个转换成对等的方法调用:Where, OrderBy 和 Select 集合。我们把你写的查询作为 Lambda 表达式语句传递给相关的方法。

这样,查询就变成连在一起的方法调用,从而查选也变得可读性更好,这就像一个语言胶水一样。上面的转换是立即执行的,如同 foreach 循环转换成:从while 循环中获得一个数字一样。这个小小的改进非常有利于你在更高的层次上思考问题。你明白我的意思吗?

Osborn:

明白。

Hejlsberg:

从这方面来讲,语法在很大程度上影响了你如何思考问题的,尽管这些语法上的东西根本和事情本身毫无关系。

Osborn:

是的。从书籍出版商的角度来看,我们公司自己的历史数据上显示,古老的C++语言有自己的地盘,在书籍出版量上只有很少的增长;去年VB的销量下降了百分之20到百分之25。C# 书籍销量还算平稳。但是很平淡。

Hejlsberg:

哦,这样呀。

Osborn:

情况很清楚,从我们的销量来看,似乎有股从VB转向到C#的动向,或者其他的。可是C++却自始至终占领者一部分市场。

Hejlsberg:

没错。VB 和 C# 在同一个程序员的群体里是相互竞争的。C++ 扮演这一个特别的角色,可是C++的核心是写非托管的代码,是相对底层的编程。我知道我刚才是泛化的说明,你也可以使用 STL 来作基于模板的编程。标准模板库有他伟大的地方。我只是说,从更广泛的背景上看C++写出的应用程序和用 VB 和 C# 写出的程序是应用于不同的目的的。

Hejlsberg:

对于C++应用领域的跌落,我感到并不惊讶。

Osborn:

我知道一个人不能用C++来写托管代码。

Hejlsberg:

从个人出发点来看,我也不会用它来写托管代码。但是,你要是让我来写一个编译器,这可不能是托管代码,那我还是会用C++的。经过这么多年的发展,我认为作为一条通用的规则,写托管代码的理由会越来越多。原因很简单啦,硬件变得更加强大,牺牲点 CPU 和内存来换取更高的生产效率来说就变得更重要了。我觉得这时一个非常有价值的命题。并且,我坚信这会逐渐的成为共识。另外,托管世界的也变得更加精彩啦。也就是,越是有创新的地方就越有更多的程序被企业所应用。

泛型和C#
Osborn:

侃了这么多,我们来说点关于 C# 2.0 的事情吧。很明显,C# 语言朝着泛型的方向发展有很长一段时间了。

Hejlsberg:

没错。

Osborn:

那么,相对于其他的语言而言C#的泛型有什么不同呢?

Hejlsberg:

哈哈,靠,很明显我更想让你说:就在C#和Java之间比较吧。

Osborn:

没错,我也是这个意思。

Hejlsberg:

首先,我非常高兴的我们在2.0里面加入了泛型编程。你现在看我们做的C# 3.0 里面的很多东西都是泛型在起作用。这的确是意义深远的,引入泛型后为类型系统开辟了一个新的空间,也打开了实现更多可能性的大门。比如:没有泛型的帮助,我们不可能做到语言级别集成的查询LINQ。从这个意义上讲,这是更多有趣功能后面的发动机。泛型也是现实编程世界里的解决方法的好帮手。

对,有更多的类型是很好的,这意味着你可以更快的发现错误,因为只有很少的运行时动态检查程序的类型,因此你可以写出很好的代码来。

现在,看看 java 和 C# 这对冤家吧,从语法学上面看两者实现泛型的形式是很相似的。他们都像 C++ 的模板,这是继承下来的。

现在我们抛开表面看本质,Java 和 C# 的泛型实现机制是截然不同的。我认为最大的不同在于:.NET平台下的泛型不只是一个语言特色。泛型根植于 CLR 和 .NET 的类型系统。这也就是为什么泛型可以在运行的时候表现出来。

而 Java 则选择了另一个不同的方式实现泛型,一言以蔽之,他们是在编译时实现的。而且 Java 编译器把泛型化从代码中移除了,并注入了对象,有效的对象替代了类型参数信息。也就是说呀,Java 在运行时根本没有泛型这一说。这就有意思啦,一方面可以让泛型跑在一个未经修改的 VM 虚拟机上,另一方面强加给你很多让然吃惊的限制和规则。相对于我们的泛型实现来说,java 的泛型并不能带来性能的收益,很显然吗,不管外表 List<T> 看起来多么泛型,Java 在运行时压根没泛型这马事儿,你不得不自己做运行时的动态检查和类型转换。

更微妙的是,因为 Java 没有在运行时的泛型信息,你从你的编译后的代码丢失了泛型信息。。如果在运气期间,有人给你一组自定义的对象,他们传递给你的仅仅是对象,如过你想从对象中推测是这些对象的更多信息是办不到的,因为额外的信息已经被移除了。

在现实世界里,我们越来越多的依赖运行中代码和动态行为的动态生成和检查,而Java 的泛型实现对我来说,是很大问题,他缺少程序运行时候的真实表现。

Osborn:

牛呀,这么说 .NET 实现的泛型允许我们……

Hejlsberg:

太对了。如果我定义一个 List<T> 作为一个 object , 我可以问 “这是什么“?系统可以告诉我,这是一个列表。他还可以告诉我们,这是一个 List<T> ,T 代表 Customers 类。我还可以说:为什么不给我一个 System.Type 的 List<T>也可以是,你为什么没有把 T 绑定到 Order ?也就是说我们可以把类型转换为 List<Order> ,并创建他的一个实例。说了这么多,总之,我可以通过反射在编译的时候,在运行的时候来实现上述功能,这是一个巨牛的功能呀。
 

Osborn:

关于增加的匿名方法有什么特点吗?我记得当匿名方法刚被人介绍出来的时候,我和其作者聊过,他说你不得不在语言中支持这样的功能,但是为什么要这么做,却说不出个所以然来。我肯定匿名方法有他的实际用处,看我们这篇报道的人也有同样的问题吧。尽管如此,在C# 3.0中支持匿名方法的特色,和泛型一样,还是很吸引人的。

Hejlsberg:

那绝对是。老实说,首先,你知道我们应该把荣誉放到他应该放的地方。我并没有在这里创造什么新的东西出来。这一切都是基于 lambda 表达式或者 lambda 微积分 的,他们已经在基于函数的编程方法里存在几十年了。然而,在主流的编程语言中确看不到他们的身影。

C# 语言有幸成为第一个实现这个特色的语言。我们是怀着严肃的态度来改进它的,这一点你将在C# 3.0中看到他们的身影。我们在匿名方法的基础上做了进一步的改进,我们成为 lambda 表达式,并给了它丰富的接口支持。

Hejlsberg:

为了表明这一点是如此的重要,我们来举例说明吧。在 C# 3.0 中我们引入了和语言集成的查询符号:LINQ。我们做的事情是:把查询的语言做成API的方式变成了可能。上面我说过,这些方法就是:Where,Select,OrderBy 和 GroupBy 等等。我们可以用一系列的Where ,Select ,OrderBy 和 GroupBy 方法组合起来,形成一个完整的查询。

如果你想在一种不支持匿名方法或者 lambda 表达式的语言中实现一个Where方法,这是不太可能的。一个 测试应用到每个元素上, 你知道我说的意思吗?我想说 list.Where(blah) , blah 是我希望在测试中输入的一个参数。

但这并不是一个普通意义上的参数,因为我并没有把它作为一个 布尔 值参数,很显然这个参数首先被计算,然后在传递进去。我并不想看到 真 或者 假,我只是想传递 测试 本身。你知道我刚才讲的意思吗?

Osborn:

是的,你想传递一个过程,然后执行这个过程。

Hejlsberg:

没错。实际上,我希望的是我引用一些代码,并且我可以执行这些代码,对不对?我希望一个方法的引用或者一个函数的引用,然后把他们传递到 Where 表达式,然后Where表达式可以为每个数据项运行这些代码,这就是测试,然后最终的结果是返回所有执行结果为真的数据项。同样的道理,如果你看看 Select 操作符是如何执行的,他和上面的道理是一样的。这就是:提供一个元素,提供一个函数他就能把元素转换成另一个元素。这就是组合的威力。

OrderBy 和这是同样的道理,提供一些元素,然后对他们进行比较。重申一遍,这些都是通过写代码实现的。在这里,最让人印象深刻的是编程语言丢失了把代码作为参数传递的能力。

Osborn:

这是非常重要的功能。

Hejlsberg:

这只是 lambda 表达式和匿名方法能让我们实现的一点事情。另外要补充说明的是: lambda 表达式 和匿名方法其实是一件事情。唯一的不同是:他们语法表现形式不同。Lambda 表达式是在语法方面的更进一步的进化。在本质上,他们是一件事情。他们的作用都是:产生方法。这就是:内联方法。

 

C# 2.0 的其他方面的亮点

Osborn:

除了 泛型 和 匿名方法外 人们还应该注意 C# 2.0 的其他方面呢?

Hejlsberg:

Nullable 类型,一个非常重要的进步。因为这是在数据库世界和通用编程世界的变得平等的第一步。你知道,在数据库中基于 Nullable 类型 而程序编程中确不是,因此这两者之间的映射很难说明明白有什么意义。

Hejlsberg:

当然,你可以跳过这些…

Osborn:

你现在要做的事情是?

Hejlsberg:

在编程过程中人们经常用装箱操作。比如:为对象分配空间,然后保存数据,如果不再使用了就设置为:null。在java中做这个是非常有效率的。但是这种方法使用起来却是非常耗费效率的。因为,为了表示一个可能值为null的整数值,在java中使用Integer封装类,为每个 int 值分配空间,然后当他们是null的时候你设置值null来实现。

Hejlsberg:

这不是直接发生的,你让每个int值耗费了4陪的内存空间。又很多耗费和这点相关。在 C# 使用 nullable 类型,我们可以非常高效的让你可以把对象值设置为null,可是并不给他分配内存空间。我们通过一个泛型类型:T 和 bool 来实现这个特性。这就是: Nullable<T> ,他的内部有2个字段: T 和 bool。

但是 Nullable<T> 本身也是一个值类型。这个类型实际上用了 栈分配 或者 内联分配,从内存的角度来看这是非常高效的。总之 , 我们使用语言语法来支持: nullable 。我们使用问号作为修饰语。

因此:int 是一个整形数据, int? 是一个 nullable的整形数据。可以把 int 隐式的转换成 nullable int ,其他方式的显式转换可以抛出 null 异常。这就是说:把人们常用的这种情况作为一等公民来对待。

对于我,一个语言的设计者,这个问题就是:人们在这里会做什么呢?在编程中什么是应该作为一等公民来对待的。

Osborn:

这么说 C# 一种语言将会统治所有其他语言?

Hejlsberg:

^_^,绝对不是啦,我真的不是这么想的。世界上还有很多其他的场合更适用于其他的语言。在 C# 的本质来说, 他是一种强类型的语言。你知道,对于很多事情来说,动态语言更适合,如果你只是准备写几行代码,并且不愿意在还没有写代码之前就要写一大堆声明。你只是想试试而已。

在语言的世界里,我希望我能够尽我所能超前发展。

Osborn:

对于 2.0 来说,我们看到微软是不是也是按照标准实现的?

Hejlsberg:

2.0吗?

Osborn:

对 2.0 。

Hejlsberg:

没错。从标准上说,叫:第三版,但实际上我们叫他 2.0 。

Osborn:

因此这里面微软没有做什么改变吧?

Hejlsberg:

没有,每个语言特色我们都提交到了 ECMA ,并且这是一个标准的过程。我们希望公平简短的社区投票,在这一点上,这的确是个问题。这些事情都已经发生了,我们已经这么干了。参考:C# 和 CLI 变得更加强大。

Osborn:

是不是大概就在今年年底?

Hejlsberg:

没错。

 

 

John Osborn 是 O’Reilly Media 公司的执行编辑。

 

 

 

 

 

 

 

 

 

 

 

 

原创粉丝点击