首页 > 开发 > 综合 > 正文

转贴:msdn 访谈录之C#编程三

2024-07-21 02:22:19
字体:
来源:转载
供稿:网友

标题    msdn 访谈录之c#编程    rainbow(翻译)关键字    c#,jeffrey richter出处    http://www.mdsn.com[tr]

程序员天地
robert hess和jeffrey richter(著名的编程作家、专栏作家和咨询专家)的谈话。

robert hess: 欢迎回来。我们正要涉及到有关c#编程方面的问题。为了有助于我们理解这些问题,我邀请我的好朋友jeffery richter到这里来。jeffery恰好是一名撰写了很多编程书籍的程序员,他最新的一本书为programming server side applications for windows 2000。现在您也是一位咨询专家并且拥有自己的公司wintellect,是吗?


jeffrey richter: wintellect。


robert hess: 我猜您有一个网站吧?

jeffrey richter:有,wintellect.com。我们专门从事培训、调试和广告。


robert hess: 好了,我了解到您最近做了不少有关c#的工作。

jeffrey richter: 是的,至今已一年有余了,我花了很大的精力一直专攻c#的编程。


robert hess:已经有一年了?我想我们才刚发布了c#。


jeffrey richter:是的,可我一直在圈内,在microsoft的圈内,如果您愿意的话。我自己在第42楼安置了一个小小的办公室,并在那里从事c#的研究和有关.net这方面的工作,到现在已经一年多了。


robert hess: 这样微软就会对您有所帮助,因为您并不是微软的职员……

jeffrey richter: 对。


robert hess:他们只是帮助您的把c#当成一种语言理解,那么您就可以写出更多象这样的书?


jeffrey richter:是的,他们希望我写更多的书,我得到了帮助,发现了bug,出席了类似的一些规范会议,并与人们交流,因此我觉得学到了很多的东西,而不只是写书,而事实在某种程度上也对c#做出了贡献。所以我可以告诉您,当最初开始时,我感兴趣的第一个东西就是这种新的语言,我将用它来写所有的代码,我知道这些代码是为可以预见的未来写的,让我们暂且不提。我具有非常深厚的c、c++背景,在阅读与c#相关文档和编程参考等资料一个星期之后,我就觉得已经相当精通c#了。并且在一周之内,我能够真正地写出一些有用的东西。

robert hess:仅仅一周之后。


jeffrey richter:是的,仅仅一周之后。因为它和c++非常类似,您知道,那里的大括号是相同的,返回值是相同的,参数是相同的,许多东西都是相同的。


robert hess:当继续使用对象、析构函数、构造函数、双冒号(::)等这些老掉牙的东西时,您似乎就要失去他们所拥有有的某些奇特的命名习惯,对吗?


jeffrey richter:是的是的,双冒号(::)都被点号(.)代替,箭头号(->)也被点号代替,这样就大大地简化了该语言。因而对于我来说实在是太容易啦,而且它还具有时效性,我仍不得不回过头去查看该语言参考资料,或许查找如何重载运算符,或者某些很平常的东西,要知道,当我编程时,极少做一些模糊不清的事。而现在大多数东西对我来说是再自然不过的了。事实上要解决的只是流程问题。


robert hess:既然您从事这项工作已经一年多了,那么您注意到了在这段时间里这种语言自身的演变吗?是否它们今天仍然与一年以前的十分相同?


jeffrey richter:我认为十分相同。但肯定存在着一些小技巧(tweak),在beta测试阶段确实存在着这些回应,存在着许多非确定性的析构函数(non deterministic destructor)、对象的析构(destruction of objects)等类似的东西。因此,基类库已经增加了一个idisposable接口,我想它将会出现在beta 2.0版中,而不是在beta 1.0版中。同时c#已增加了一些新的语言结构,以帮助你获得与对象的确定性析构(deterministic destruction of objects)关系密切的东西。所以我要说,微软已经十分在意人们对该语言的评价了,并且他们还企图在其中加入新的东西以做出回应。我同样了解到,将来在1.0版之后,他们计划要增加泛型(generics),这有点类似c++中的模板,而我可以肯定,为了支持这些性能,c#就要发展。实际上当处于公共语言运行库(common language runtime)之中时,所有的语言都能用到泛型。

robert hess:因为它们是其中的一部份,又因其是公共语言运行库,所以它们有权使用所有的那些功能。那么您认为,c#作为一种语言总的来说究竟怎么样?


jeffrey richter:嗯,正如我所说的,c#与c++非常相似,所以我很快便熟悉了。它非常非常的干净,我要说它是非常干净的。我出身于c++背景,尤其是作为一个windows c++程序员。ansii拥有c++规范,微软为了展示windows中的功能,就想在c++中保留一些技巧,并且使这些技巧看起来有点像c++中的贵族,可它们从来就没有真正地达到要求。而微软仍陆续增加__try、  __finally 和 __declspec等类似的东西。


robert hess:这就是您正在谈论的c#。


jeffrey richter:对,当然还有c++。因此,这种语言确实有点恐怖,过了一会儿您还是不会完全弄明白,就如const的用法,当声明一个指针或者是一个常量指针时,星号(*)究竟应放在它的前面,还是放在后面?您将无法断定这些修饰符到底应放在该行的那个位置。我总是需要查资料。因此在c#中,由于微软在设计时已经预先向ecma(欧洲计算机制造商协会)做出了要求标准化的提议,所以它实在很干净,例如,没有什么是以下滑杠开始的。当然,由于本来在.net runtime中就没有真正的指针,所以在您的代码中,从头到尾都不会能见到*号和&号等此类修饰符。这样当考虑它时,看起来干净,真的觉得很爽。

robert hess:难道您不觉得缺少什么吗?我的意思是,当我在用c编程时,喜欢运用指针解决问题,对指针重新分类,利用指针算法等老掉牙的东西,您就会从中获得极大的乐趣。难道您在用c#时就不怀念它吗?


jeffrey richter:嗯,我不得不承认,我自己总是有些喜新厌旧,但有时也有点念它。当然总的来说,有了c#和.net framework,您就可以始终与其它语言进行交互操作(interoperate out),因而如果真的必须那样做的话,我便用c++而不是c#编程了。c#也确实提供了一种不安全的关键词(unsafe keyword),这样一来,您就可以创建一个方法并且说,这是不安全的,您有权使用指针并对内存进行直接操作。尽管如此,我还是从未亲自体验过。至于编码时获得的乐趣,.net framework和基本os类库提供了大量的特性,它们使编程变得有趣了。因此,当我不能保留虚拟内存并稀疏地提交,也不能在.net framework中利用内存映象文件进行工作时,至少不能直接进行时,也可以通过交互操作完成,仍然还有其它类似serialization和web服务等东西,它们有利于创作出真正有价值的应用程序,真正强大而丰富的内涵。


robert hess:如今在您的培训班里,您正在教授和灌输这样的东西,您还在办c#的培训班吗?


jeffrey richter:是的,事实上刚好这一周,我给第一个c#编程班上课,当时班里有两个visual basic程序员,他们根本就不是面向对象的程序员,而我也没有真正地给他们介绍过c#语言,因为我把重点放在公共语言运行库和基类库方面,有关c#的内容想稍后再讲。但是,这两个vb程序员在上机实习时,对c#上手很快,几乎没有遇到什么麻烦,而且竟然能用其进行开发,效率也高。我十分惊讶!


robert hess:其中的原因是由于在c#中,您使用name.name.name.name,而不是name、->、name.name、-> name.*、*、()、&等老掉牙的东西……


jeffrey richter: 确实这样。


robert hess:这些在vb中都不会用到。


jeffrey richter:正确。


robert hess:所以格式看来相当一致。


jeffrey richter:对,相当一致。当然,他们用大括号{}而不是begin和end,这可能使有些人不适应。但我认为,他们最多花不到5分钟的时间就可以克服它,而且更多产。


rrobert hess:那么以一个公司的立场,假如一个公司聘请您去开设一个c#培训班,因此我得去发现他们是否开始考虑把公司的一些成果移植到c#,这就是您建议他们要做的事吗?或者您认为他们应处于哪一个阶段?


jeffrey richter:嗯,当然它取决于,首先他们必须决定是否要采用.net framework作为开发平台。我认为这非常有价值,对于我来说毫无问题,那是我真正向往的平台。如果您正在开发.net framework的应用软件,正在编写新的代码,在我看来会不费吹灰之力。 c#上手实在是很容易,它是一种生机勃勃的语言,使用正确的方法您会非常多产的。我个人也相信大量的vb程序员,vb6.0程序员,将会转向c#而不是vb7.0。


robert hess:那为什么?


jeffrey richter:因为我认为c#揭示了公共语言运行库(common language runtime)之中的更多的特性,使您对代码及其所表达的方法具有更多一点的控制权。您将更直接地与runtime对话,runtime赋予了您更多的权力。


robert hess:当然,我们本身谁都不是vb程序员,所以将明确地在c基础之上发展。


jeffrey richter: 您是对的。


robert hess:所以这正是它物有所值之处,我们有点偏离正题了。那么作为一种语言,您喜欢c#的哪些方面呢?是更简单、更彻底(clean)的编程吗?

jeffrey richter: 嗯,主要是去掉了无用的东西。 譬如, 嗯, c#不允许您把参数作为常量(const)声明,并且您不能拥有一个const的实体方法,而在c++中则可以。我知道某些人会认为那样会真的丧失语言的特性,但事实在c++中,const总是会被无情地抛弃,这样您就能在自己的代码中为所欲为了。由于c#实在是不允许您使用const,所以它又彻底又易于理解。现在,我想我应该说:对于我,.net frameworks真正有趣的东西就是公共语言运行库。它定义对象如何运转,或如何创建类型,以及是什么定义了这些类型的行为。这样您就拥有了一个基类库,当然它是一个巨大的类库,它让您有权使用大量的东西,所以即使您愿意,也不必再三重写每一样东西了。您选择语言是您个人的事情,而我选择了c#是由于它是真正优秀的高阶语言,它让我能与framework对话。但在某种程度上,运用.net runtime和基类库真正最佳的语言应该是中间语言(immediate language)汇编语言。


robert hess:哈!谈到汇编语言啦?

jeffrey richter:是的,谈到汇编语言了。我的意思是,它使您完全有权访问平台的底层,但在汇编语言的环境中效率会很低,有这么多的程序您必须一行一行地写。所以,c#语言高出了一个层次。而在c#中的有些性能并不是很常用,因此象anders 这样的c#设计者已决定不必将其公开了。在某些情况下,为了访问c#没有提供的runtime功能,我可能会求助于另外一种语言。但总的来说,c#是最高层的语言,它允许我在这样的环境中按自己的需求解决大量的问题,而且效率极高。

robert hess:并不是所有的问题,而仅仅只是大部份?


jeffrey richter:不,极少会出现这种情况:我还需要访问某些东西,而c#却不让访问。这是另外一方面,我只是认为大家非常容易忘却的是,当您想要访问.net的一些功能而c#或某些语言却不提供给您时,可以转到别的语言。只需编码创建这个方法,可能是一个静态方法(static method),类中的静态方法,用apl或cobol或凡是您选择的语言,或许派生,然后用某些语言实现实体方法,而这种语言可能真的让您访问某些底层功能。因此,我认为这是一个功能非常强大的范例,以前我从未真正地领会过要选择最佳的语言去完成工作。

robert hess:好了,我打赌各位观众可能想要看一些c#代码的例子,以便能理解我们谈论到的一些问题。您有例子示范给我们看吗?

jeffrey richter:有。我确实的带来了一个源代码文件,里面有一些例子,能勉勉强强地应付,在节目结束后,我会给您的。欢迎您把它上传到网站上,以让大家可以下载。所以在这里,如果你样喜欢的话,我首先要示范的是:在c#中,每一个方法必须位于类中。没有全局方法,也没有位于类之外的变量,所以每一样东西都会被限定在一定的范围内。
using system;

class app {
   public static void main() {
      console.writeline("hello world");
   }
}
这是一个必须保留的hello world程序,非常简单。在程序里,有一个类叫app,在这个类里,我拥有自己的一个main方法,并且main是一个静态方法,因为它必须从外面调用。我们不必拥有app的一个实例就可以调用main。在我这个例子里,main返回void,并且没有接受参数。简单地在main的内部,它调用了console.writeline,在显示器上面显示出"hello world"。所以这是您可以写的、能学到相关概念的最小程序了。

robert hess:在c#中main仍然是一个保留的方法吗?就象在c++中?


jeffrey richter: main是默认的,它具有大写字母m,小写字母a-i-n ,因为c#是字母大小写敏感的语言,象c++ 而不象vb 和.net 。所以当编译器编译代码时,将寻找一个叫做main的静态方法,然后再使用它。然而有一个编译器的命令行,它可以覆盖掉main并选取其中不同的一个。顺便说一下,事实上这是一门很有用的技巧。一些人把多个main放到一个单个的应用程序里,以便进行组测试,当编译时,可以设置不同的开关执行不同的main,以便测试特定的组件。


robert hess:绝妙的技巧。您也使用象argv、 argc这样的参数,默认地传递给main函数吗?
using system;

class app {
   public static void main(string[] args) {
      console.writeline("hello world");
   }
}

jeffrey richter:是,随您的便。在这里,我将当场修改这些代码,也就是说,string是一个字符串数组,args 按我在幻灯片中播放的定义。顺便地,这个args是什么呢?是一个数据类型!它是一个指向字符串的指针,或者是一个指向字符串的引用。说到指针,您只见过带*号的,但args确实是一个指针。当main被调用之前,启动代码早已解析命令行,并且创建一个字符串数组,接着把指针传入该数组。象对args.length类似的调用使我可以解决一些问题,该调用会返回数组的length属性,此属性含有数组元素的个数,然后我正好可以利用一个正常的for语句进行循环,或者可以用c#的for each,特殊的for each语句用于快速的循环。

robert hess:很新颖,这是在c或c++中所没有的。


jeffrey richter:正确。而我确实也有演示的代码,我找到了。
static void arraydemo() {
   // 声明一个指向数组的引用
   int32[] ia; // 默认值为 null
   ia = new int32[100];
   ia = new int32[] { 1, 2, 3, 4, 5 };
   .
   .
   .
这是一个具有数组的代码的例子,所以我会略为提一下。在这个例子里,首先声明一个指向int32s数组的引用,随意取一个"ia"用于整数数组。它只不过是一个指针,具有32位(bit)或64位值,如果它们仍在64位系统上运行,总是会被初始化为null,引用总是被初始化为null直到明确地设置它为止。下面一行,我随意new(构造)了一个有100个int32值的数组。new返回一个引用,接着我把这个引用存到"ia"变量中。下一行只不过演示了另外一种构造的方式,这里我又new了一个int32s数组,这种专门的c#句法以一个左大括号开始,后面跟着数组的元素,当然元素之间要用逗号分开,然后是一个右括号。当您第一次见到这种句法时,会觉得它有点笨拙。这只不过是new的另外一种用法,当然它可以推算出元素的个数。

robert hess: 而这只不过是预定义了值:
   .
   .
   .
   // 显示数组的内容
   foreach (int32 x in ia)
      console.write("{0} ", x);


   //使用多维数组
   stringbuilder[,] sa = new stringbuilder[10][5];
   for (int x = 0; x < 10; x++) {
      for (int y = 0; y < 5; y++) {
         sa[x][y] = new stringbuilder(10);
      }
   }

   // 使用数组的数组(jagged arrays)
   int32 numpolygons = 3;
   point[][] polygons = new point[numpolygons][];
   polygons[0] = new point[3]  { ... };
   polygons[1] = new point[5]  { ... };
   polygons[2] = new point[10] { ... };
}

jeffrey richter:是的,很正确。这就是foreach,它出现在代码的第一行。"foreach"是c#句法,我肯定所有的.net语言都会提供此句法,它是一个极其通用的编程典范,用这种方式,就可以遍历集合里的元素。因此,这里的foreach int32 x中,"x"是一个变量,int32当然是一种类型,接着我把引用赋予了数组。foreach将会自动推算出数组中有多少个元素,并且每当循环到console.write时,就会显示出元素的值,然后再移向下一个元素。

robert hess:而"for (i=0, i<ia.length, i++)"也做同样的工作,但如果您想要遍历所有的元素的话,这种方式有些笨拙以至难于遵循,所以一直持续不断地做十分相同的事情,我想会更加容易。

jeffrey richter:对,精辟。尽管如此,我会给您一点提示,由于foreach有点酷,也十分精巧,因此省去了大量的编码。它也另外做一些有关类型转换(casting)的工作,这对您同样也有好处。所以一般来说,当我写一个循环时,我通常会以foreach开始,然后当我继续编码时,有时经常地,我随后认识到我需要一个迭代器(iterator),需要一个从0到实际数字的x。是的,我必须知道哪一个元素号。所以我终止了重写这个循环,相当频繁……

robert hess: 噢,真的吗?

jeffrey richter: 是真的。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表