转贴: MSDN 访谈录之C#编程一 rainbow(翻译)
2024-07-21 02:22:19
供稿:网友
标题 msdn 访谈录之c#编程一 rainbow(翻译)关键字 c#,msdn出处 http://www.msdn.com
msdn 访谈录(msdn show)
c#编程
c#是一种令人耳目一新且为之一振的编程语言,它设计给c++程序员带来快速的开发能力,而又不牺牲c和 c++所特有的功能和控制。
在今天的这一期里,我们将要和anders hejlsberg交谈,他是微软一位资深的工程师,一直帮助设计、开发和实现该语言,并发挥其在未来.net平台中的作用。我们还要和jeffrey richter(著名的编程作家和咨询专家)交谈,他从事c#的工作已经一年有余了。
介绍
robert hess,微软产品经理和“show”节目主持人。
robert hess: 让我们继续关注理解.net体系(architecture)。我们今天将关注新的c#(念“c sharp”而不是“c pound”!)编程语言。首先看看msdn 消息更新栏目。
msdn 消息更新
由技术编辑erica wiechers主持
(略去与c#无关的谈话)
技术闲聊(techno babble )
robert hess和资深工程师anders hejlsberg会面,要讨论…???
robert hess: 欢迎回到这个栏目。好了,就象任何一个要在其上面开发软件的平台,为了使这些应用软件能真正地运行起来,所需要的一个主要东西就是一种编程语言。目前,.net已经拥有了一种专门为此开发的专用语言,我们称之为c#。今天和我们在一起的是anders hejlsberg,他是微软一位资深的工程师,在c#语言以及.net平台领域都扮演了一个关键的角色,在以前的“show”节目里大家都见过他。所以我邀请他到这里来,和大家一起谈论c#,谈谈它是什么,有了它程序员就可以从中得到什么好处,以及它是怎样真正地影响到应用程序的开发的。
那么,您究竟从事c#哪方面的研究工作,是从什么时候开始的?
anders hejlsberg: 在最近大概两年半的时间里,我们一直在从事c#的研究工作。设计小组由4人组成,而且在这段时间里,我把主要的精力都放在了这上面。要知道,对于一种新的编程语言,我们有许多事情要去做。我想首先也许就是为程序员提供方便,使程序员开发出更多的产品就是最终目标。如今,虽然在产品的收益方面仅仅只是初具规模,但可以说,我们的目标,在某种意义上,不但要使c#具有c++强大的功能和出色的表现,而且还要使其具备简单易用以及rad(rapid application development,快速的应用程序开发)语言的生产率。
我们已经做了一些工作,例如,涉及到程序员如何利用更好的工具编写组件的范畴。如果你看看我们是怎样写应用程序的,应该是曾经怎样写应用程序的,如果回顾过去,也就是说5年或10年以前,应用程序就是这样铁板一块地被创建的,它和操作系统的唯一交互,你知道,就是进行文件的i/o操作,而且无论如何操作系统都会载入应用程序,接着用户就与其交互,最后退出。看看现在我们是如何创建internet应用程序的,相比起来简直是天壤之别。应用程序不再是铁板一块了,而是由一系列更小的组件构成,它们分别栖息于不同的环境。例如,你可能拥有类似存储过程(stored procedures)和sql server那样的组件,也可能拥有栖息于浏览器中的控件,或者是存在于asp网页中的代码。商业对象生存于中间层,调用整个集合的组件就等于调用该应用程序。于是为了使……
robert hess: 而当时您明白其中的每一个组件都比5或10年前的一个应用程序更加复杂。
anders hejlsberg: 噢,绝对,绝对。同样,为了减少创建组件的复杂性,不象那种大块头程序,每当必须创建其中的一个组件时,就不必另起炉灶,而应该尽量继承一些早已存在于这些专门的栖息环境(hosting environment)中的东西。如果要写浏览器中的一个控件,就要继承一个基控件;如果要写中间层的一个商业对象,就要继承某些商业对象类;而要想公开属性、方法和事件等等,就要说明它们是如何通过把属性与组件联系一起,以便与栖息环境相结合。而且还要能够为这些组件撰写随组件一起发布的文档。
robert hess: 所有的这些只是标准的面向对象的编程,smalltalk 拥有此特性的时间似乎已经不短了,并且……
anders hejlsberg: 嗯,绝对如此,现在并不是不能做这样的事。但如果注意一下这种今天已经得到了广泛应用的编程语言,它们实际上并不真正支持面向组件的概念。如果你当初同意我们什么时候谈论组件,那么认为它们具有属性、方法和事件在当今是极其平常的。但如果注意一下c++,就会发现它仅仅提到“方法”这个概念,没有属性,也没有事件。现在,你可以利用命名模式来仿真它们,也就是说,对于一个属性,可以用一个get color和一个set color的方法来取代一个color属性;而要代替类中作为第一个类成员的事件,你拥有的用于接收事件的接口就应该被实现,为了这样,你就必须处理一些琐碎的事……
robert hess:嗯,部分原因是由于c++是基于c的,它只是象预处理程那样,又由于c本来就不支持,c++也不支持……
anders hejlsberg: 是的,实际上我多少认为,你所看到的就是从c到c++再到c#的发展过程。从c到c++,面向对象编程的概念被加进去了。如果你经历了从c++到c#,那么我会说,面向组件编程的概念也已经被加进去了,而它们之间真的存在着某些相似的地方。就象可以用c代替c++进行面向对象的编程,你也可以用c++代替c#进行面向组件的编程,只不过是更困难而已。用c来进行面向对象的编程是极其困难的,你必须手工地布置v表(虚拟函数表),并且还要处理所有琐碎的事情。用c++写组件也确实可行,但必须要为属性手工地设置命名模式(naming patterns),必须实现事件同步(event syncs),必须具有外部的idl文件,在文件中可以对栖息属性(hosting attributes)进行描述,必须具有外部的文档文件,等等。我们只真正采纳了其次一个合理的步骤,它反映了人们是如何编写应用程序并把其整合到语言中的
robert hess: 那么,最初的一些目标是什么?仅出自内心的看法,当您第一次着手这个项目时,您要解决的问题和要确定的这种新语言的方向是什么?
anders hejlsberg: 嗯,我认为正如您所说,面向组件只是一方面。我想另一个关键的因素就是简单化。使编写应用程序更加简单化,不让程序员做一些琐碎的事,机器可以代你做。大量的简化取决于.net runtime本身,但也取决于语言。基本上,最终我们所做的,就是让你把更多的时间、更多的精力放在算法上,而让系统去做一些琐碎的事。我认为,许多其它非常关键的事情比较现实,我总不能吩咐人们把他们现有的代码通通扔掉吧。我们必须找到权衡的方法,并不仅仅是你的编程技巧,而且还包括你以前编写的、早已存在的代码。因此在c#里,以权衡你技巧的名义,我们努力坚持在与c++的基础语法最接近、最真实的地方。所以用了c#,c++程序员会立即觉得很眼熟、很亲切。
robert hess: 您的所做的一切应当以c语言为基础,是否就是当初的思路之一?或者您是否原来就认为,让我们应与过去彻底决裂,再开始设计一种全新的语言?
anders hejlsberg: 嗯,我想这种语言应该以一种崭新的面貌出现,可是我们明白,必须让c和c++程序员熟悉这种语言。当然那就意味着在某种程度上,我们必须把语句结构从弯曲的大括号变换成其它一些东西。我们已经打下了一些基础,但仍然存在着其它某些关键的规则,譬如允许写健壮的软件,这就意味着象垃圾回收(garbage collection)、异常处理、类型安全这样的功能,根本地改变了设计该语言的思路,非常难于上手,以后也不容易扩展。我的意思是说,在c++中,c++语言拥有的一个强大功能之一,但有时也同样是难点之一,事实上您知道,就是没有类型安全。如果你了解清楚自己要做什么,就会从中获取巨大的力量,否则,只是自找苦吃。在c++中,获得一个虚悬指针(dangling pointer)易如反掌。同样,覆盖掉一个数组的尾部,或者拥有一个未初始化的变量等等,也是极其容易事情。而我们需要解决这些难题。我认为,我们不能只从 c++着手并扩展它。而真的必须以退为进,以c++的灵魂设计出新的方案,而这些我们已经差不多完成了。
robert hess: 那么其它语言呢?您注意到这些语言在做了什么吗?是否它们就是pascal 或 modular 2 或 forth,您从中得到什么借鉴?
anders hejlsberg: 绝对!噢,我们考虑到,嗯,我的意思是说,我本人出身于深厚的pascal背景,所以,自然要考虑到pascal, modula, oberon, 要考虑到smalltalk,java,c++以及所有的语言。要知道,今天它们能生存下来并得到了应用,且或多或少地传播开了。
robert hess: 您觉得这些语言的哪些功能比c和c++表现得更出色?而您就可在新的语言中引进这些功能?
anders hejlsberg: 嗯,我认为有一件事可以说明,我总是喜欢smalltalk,就是因为在该语言中,任何东西都是对象。这使程序得到了大大的简化,因为无论拥有什么样的数据片,都可以把它当作一个对象从a点搬到b点。一般来说,任何东西都可以对其进行操作。可以把它当作对象类型,放在容器中。在smalltalk实际的实现过程中,如果这样做的话,程序性能的额外负担(overhead)就会大大加重。例如,在smalltalk中,当运算float数字时,每生成一个新的数字,如当1.0和2.0加到一起时,就要分配一个含有3.0值的新对象。而这样做,代价当然是非常昂贵的。如今在c#中,我们已经进行了一些革新工作,使你获得了同一样的利益,而却没有额外负担。只要把float当成float,或者是double就把它当成double使用,就没有什么代价。但如果把它们视为对象(也仅当这样做时),就得给它们分配堆(heap)。因此,就形成了样相当完美的统一体,既能给您大量的好处,而又没有程序性能的额外负担。
robert hess:c#生成的最终结果的某些结构到底如何?您得到了一个c#程序的文本文件并且编译它,那么编译器本身存在着些什么问题,如何设计这些方案以便在使用时更具效率,而这种优化其它语言有可能已经做过,而甚至最终还要生成二进可执行文件吗?
anders hejlsberg:嗯,我们已经做了一些涉及到如何编码的工作。假如你是一个c++程序员,当然熟悉怎么做,在c++中声明和实现是分开的。所以所有声明都放在h文件里,接着在另一些模块中把它包含进去(# include),然后再在cpp文件中写出实现程序。在c#中,把它们都写在同一个地方。这样,可在那里写出声明接着又立即写出实现代码。
robert hess:假如您必须在另外一些文件中采用在main文件中声明的某些值,那又怎么办?
anders hejlsberg:那么会出现什么情况呢?当编译时,实际生成的代码或重新生成的输出文件都含有两种代码:元数据(metadata),符号表(symbol tables)或其它相关的符号信息(symbolic information),而不是仅生成只含有可执行代码的x86机器码。在某种意义上,这些代码变成了自我描述。所以当想从一个代码片使用另一代码片时,只要引用它们便可,而这些代码的自我描述足以让人们知道在那里有什么类,类拥有什么成员,可以调用什么方法,属性是什么以及类型名是什么,等等。
robert hess:那么,是不是象您所指的.obj文件或.exe文件,抑或……
anders hejlsberg:嗯,您说的很对,我们在.net中使用的格式就是pe格式,故可以指向另外的exe或dll。我们现在调用这些汇编程序,并基本上用这种语言大量地描述这些高级dll,它们不仅含有代码,也含有这样的信息:说明什么在代码中,以及这些代码真正地引用了其它什么样的汇编程序。
robert hess:您所说的代码是指二进制代码或可执行代码。
anders hejlsberg:嗯,实际上,我们并不直接生成可执行的x86机器码,而是生成msil,也就是中间语言,它由.net定义,并由jit(实时编译器)编译。
robert hess: ok,这样看来,您拥有了一个可执行文件,其本身与中间语言以及元数据相关联,而如果我想要在其中一个应用程序里使用它,我只要指向它并说道,嘿,我要借用这些类,借用这些对象,并在这样的程序中使用它。这使我想起了许多人曾经提过的一个问题,涉及到中间语言存在着潜在的漏洞,有些人可能会攫取这种文件并对其进行反编译,然后再恢复成当初的源代码。因此,并非所有的智能特性(intellectual property)都有利于开发者。这方面还有什么问题?
anders hejlsberg:嗯,首先,您现在实际上可以用dll进行处理。这可能有点难,但您可以采用包含x86码的一个dll,然后至少把它反编译成汇编程序。您可做同样的……
robert hess:在我的apple ii上,我一直都是这样做的。
anders hejlsberg: 确实如此,我对此感到惭愧。但是运用.net dll并把其反编译成msil,也可以做相同的工作。它们并不能直接地被反编译成c#,尽管您也有可能蒙对,但太难了。不同的地方在于,有着非常多的符号信息(symbolic information)关联到由c#生成的代码,以及msil,对不起,是.net汇编程序。例如,你可以从代码中得知,什么类在这里,它们的成员是什么,等等。这是一个需要解决的棘手问题,因为让代码自我描述(self describing)的好处多多,但事实上代码对自己进行的描述,也同样使反编译工具所处理的代码变得似乎容易理解了。如果我们认识到这个问题,基本上我们要做的,就是创建一个称作搅拌机(obfuscator)的东西,它会加入并搞乱代码,使代码变得几乎难于看懂,可仍然保留着原来相同的公共接口。
robert hess:是的,因为您遇到这样的难题:当采用、编写这些编译器程序时,就想让编译器理解代码(或类似的过程等),但却不想让人们在同一层次上看懂它们。
anders hejlsberg:确实如此,确实如此。我确实想指出,对于一个小程序,实际上可以对其进行反编译,给出足够的时间和资源,你甚至可理解它在干什么。然而对于真实世界中的一个应用程序,这却是一项艰巨的任务。在现实中你最好运行这个应用程序,理解它在干什么,然后写出它的一个copy。你会很快达到这个水平的。
robert hess:或许写出一个更牛的程序,因为您是一个更牛的程序员,对吗?为了断定我们的观众是否想要着手实现下一个c#项目,他们需要去理解有关c#的一些什么问题?
anders hejlsberg:嗯,我想首先你必须考虑到自己的基础。如果你有现成的代码体,让我们假定它是用c++写成的吧,也许把这些代码移植到.net framework的最佳途径就是使用managed c++,该c++编译器随.net一起发布。然而,如果你着眼于编写新的代码,也就是写新模块、更大的模块,加入到一个应用程序或一个完全了解的应用程序中,而且你精通c++,那么我建议考虑c#。
robert hess:因此,我们没有必要说,每个人都必须用c#重写他们的应用程序。我们在说,人们必须了解他们目前所从事的工程的类型,是否是一个现成的项目、陈旧代码,并且有时还要用c#写一些组件,莫非您可以交替地使用c#和c++?
anders hejlsberg:噢,绝对。首先,如果你拥有现成的代码,假定这些代码是由windows平台所支持的任何一种语言写成的,则把它们编译成com组件或dll,就会获得与这些代码很强的交互操作能力(interoperability)。如果要写专门用于.net framework的代码,用于.net framework的新代码,当然要用.net framework所支持的任何语言写。我们计划在visual studio .net中发布四种语言:c#、 c++、 visual basic 和 jscript。可是为了与产业界和学术界合作,我认为,最新的统计可能不是很准确,但我想总共大约17种不同的语言现在都瞄向了这一个平台,其范围一直从apl到cobol。
robert hess:那么象fortran又怎么样呢?
anders hejlsberg:我相信相关的工作正在进行中,可我不能准确地知道到底谁正在设计fortran编译器。但关键的是,实际上我们已经做了多次示范了,你可以在c#中写一个基类,并在c++中继承它,然后再用vb程序创建它的一个实体。在不同的语言之间进行的互用操作是无缝的。我想正是这些性能,使.net framework甩开产业界中其它竞争对手的产品。(有兴趣的读者可以到http://www.lahey.com/net_down.htm去下载lahey/fujitsu fortran for .net technology preview 1,译注)
robert hess:而且它采用并允许在基础层次上进行多语言的互用操作。
anders hejlsberg:是的,很准确。不过是位于一个很高的层次。您可能会争辩:现在的语言可以进行互用操作,但只能位于很低的层次,例如,dll的入口点、具有指针在其中的结构,等等。而我们正在谈论到更高的语义层次,是位于面向对象的层次,具有类和接口等等。