首页 > 开发 > 综合 > 正文

C#学习笔记(4)

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

约定

//一个典型的用c#写就的helloworld程序
using system;
class helloworld
{
public static void main()
{
console.writeline("hello world !");
}
}

我忘记自己第一次用c#向世界问好是在什么时候了,不过可以肯定我已经打过招呼了,那时候用的是beta1版。现在你可以到http://msdn.microsoft.com/downloads/default.asp?url=/downloads/sample.asp?url=/msdn-files/027/000/976/msdncompositedoc.xml去下载.net framework software development kit (sdk)的正式版,其中包括了前面提到的.net framework, 以及书写、编译、测试、开发 .net framework 应用程序所需要的一切??文档、例子、命令行工具和编译器。安装之后就可以开发和运行c#程序了,不过一般的建议是:一定要看.net framework sdk中所带的文档与例子,如果能照着例子再写一遍那就再好不过了。
当我第一次看到c#代码的时候,同样认为它很像java,一个形象的比喻是:c#和java是一对双胞胎,从语法的角度来讲,它们共同的父亲当然非c++莫属(请注意,不是vc++)。对于一个学过java语言的人来说(比如说在下),要理解这段代码实在是太容易了:第一行当然是注释了,c#支持两种注释方法,以"//"开始的单行注释和以"/*"、"*/"配对使用的多行注释。第二行(using system)导入了system这个包(在c#中被称之为名字空间,namespace),可以让我们方便的调用microsoft.net基类库system中的所有类,在此例中使用了system名字空间中的"console"类,用于在控制台窗口输出程序运行结果。如前所述,c#并没有内置的输入输出语句,所有需实现的功能都完全来自于.net基类库。这一句的作用就是告诉编译器去哪里寻找console类以便调用。
接下来声明了一个类helloworld,这个类中有一个特殊的方法main(),每个可执行文件都需要有一个入口点,在c#中,这个入口点就是main()方法,此方法将在程序启动时被调用。在这个方法中,console是在命名空间system下的一个类,它表示的是控制台。这里调用其静态方法writeline()。如同c++一样,静态方法允许我们直接作用于类而非实例对象。writeline()函数接受字符串类型的参数"hello world !",并把它送入控制台显示。如前所述,c#没有自己的类库,它直接获取microsoft.net系统类库。在这里正是通过获取microsoft.net系统类库中的system.console.writeline()来完成我们想要的控制台输出操作。现在使用记事本来编写这段代码,并将它的文件名保存为helloworld.cs,其中".cs"是c#源代码文件的扩展名。然后在配置好c#编译器的命令行环境里键入"csc helloworld.cs"编译文件。可以看到编译输出文件helloworld.exe。键入helloworld执行这个文件可得到下面的输出:

hello world !

这就是第一个c#的程序,我们使用csc.exe来编译它,对于这个c#编译器,有如下说明:
1. 它是随.net framework sdk免费发布的,可以在dos命令行被调用
2. 它的使用方法如下:
  csc sourcefile.cs /out:targetfile.exe
  如果不使用输出参数指定目标文件名,则默认输出为源文件名
3. 一般情况下,它在系统文件夹(windows或winnt)下的microsoft.netframeworkv1.0.3705文件夹内
4. 如果你安装了vs.net,从visual studio.net tools项目组中可以激活visual studio.net command prompt窗口,这是一个配置好c#编译器的命令行环境
5. 使用csc.exe编译后的c#程序并不是机器代码(尽管拥有.exe的后缀名)。如前所述,c#程序只是被编译成了msil代码。

c#编译器(csc.exe)编译后的文件并不是一个严格意义上的可执行文件(并不包含机器代码),而是一个pe(portable executable)格式的文件,虽然它同样拥有.exe的后缀名。在这个pe文件中也不仅仅只包含中间语言,在其中还包含有元数据(metadata)和一个由编译器添加的目标平台的标准可执行文件头。

中间语言,确切地说,应该称为微软中间语言(microsoft intermediate language,msil),是由微软定义的一种界于源代码与机器码之间的一种语言。在clr中,它首先会由特定的语言编译器将其包装成exe格式的伪代码(p代码)。再由特定的编译器将其转换为本地代码执行。对于微软中间语言,一个形象的比喻是:如果clr是操作系统的话,那么微软中间语言就是.net平台上的asm汇编语言。它比大多数 cpu 机器语言更为高级,比如它可以理解对象类型,并具有创建和初始化对象、调用关于对象的虚拟方法以及直接操作处理数组元素的指令。它甚至还具有发现和捕获异常情况用于错误处理的指令。

元数据(metadata)和msil共同存在于编译好的程序文件之中,描述了此程序包含的类型的定义、各种类型的签名及其它一些数据,相当于以前的类型库(type library),同时也记载了此程序所引用到的其它外部类。元数据的主要作用是将与代码有关的更多的信息提供给clr。基本上,元数据用于如下各项任务:用于表示clr用途的信息,如定位和装载类、内存中这些类的实例、解决调用、翻译il为原始码、加强安全并设置运行时上下文边界。

一个由c#语言写就的源码文件在clr环境中执行的过程是这样的:首先由c#编译器编译成包含了中间语言和元数据的pe文件,当我们在系统中调用这个文件时,clr会启动一个编译器再将这个pe文件包含的msil代码转换成为托管的本地代码。转换msil代码为本地码的这个编译器就叫做jit编译器(just in time,jiter)。请注意它并不是前面我们用到的c#编译器。
现在让我们看看jit编译器是如何工作的:当pe文件被调用时,jie编译器将其分解为msil和元数据,这时候msil并不直接让.net去调用本地的系统接口,而是指定.net系统去编译连接那些需要的clr dll,编译出百分之百的本地代码。整个的过程如下:
当一个类型被装载时,装载器创建一个存根(stub),并使它与类型的每一个方法相连接。当一个方法第一次被调用时,存根把控制交给jiter。jiter把msil编译为本地代码,并且把存根指针指向缓冲本地代码。已经被jiter编译的方法随后就直接调用已经产生的本地代码,减少了jiter编译和执行代码的时间。可以看到,jiter并不会一次性的将所有的msil都编译为本地代码,而是在我们需要时才即时编译,也就是说,有些代码可能从来都没有被编译过。很明显这样做的好处是既保证了运行期的安全性,又不会损失太多的效率。

这就是一个c#程序执行时的步骤。整个过程是这样的:
1) 由c#编译器将源代码编译为中间语言
2) 装入托管代码,这包括解决内存中的名字、表层类(laying out classes ),并且创建jit编译所必需的存根。通过执行经常性校验,包括加强一些访问规则,类装载器同样也增强了安全性
3) 用jiter将 il转换成原始代码
4) 装入元数据、校验类型安全和方法的完整性
5) 垃圾收集(gc)和异常处理
6) 描绘和查错服务
7) 管理线程和上下文以及远程管理。

不必全部理解这些概念,在以后的学习中将会一一的体会到它们的精彩,现在你需要做的(如果你还没这么干过的话),是找到ildasm.exe这个文件(一般情况下,它会和csc.exe在同一文件夹中)。顾名思义,这是一个msil的反汇编程序(.net framework il disassembler),在命令行窗口下输入ildasm helloworld.exe /out=helloworld.il就会得到两个文件:helloworld.il和helloworld.res。前者包括了反编译出来的元数据和msil代码,后者则是提取的资源文件。用记事本打开helloworld.il文件,可以看到它定义并实现了一个继承自system.object 的helloworld类及两个函数:main()和.ctor()。其中.ctor()是helloworld类的构造函数。在这个文件中还包括元数据和其它有关的信息。如果你觉得这样不够直观的话,可以在命令行窗口键入ildasm helloworld.exe,这样就可以启动ildasm 窗口并向我们展示出反编译后的helloworld.exe文件。

请仔细将这些代码看上几遍,现在理解全部这些内容并不重要,但是希望你也能看一下文件中的元数据,这其中包含所有 runtime 和编译器需要的有关程序集及其模块、类型和成员(如方法)的信息。

行文至此,我想谈一下学习。如你所知,在我们所处的环境中,学习总意味着是一个痛苦的过程,学习一种新知识好像总是为了自己的某种需求,我并不认为这样有什么不对,但我总觉着,除了拿到高薪和受人尊敬外,学习还应该带给我们更多的快乐。有些知识我们现在也许用不着,比如前面谈到的一些内容,但是我们了解了,就是一件值得高兴的事。

智慧本身就是好的,有一天我们都会死去,追求智慧的道路还会有人在走着。死掉以后的事我看不到。但在我活着的时候,想到这件事,心里就高兴。 ??王小波

今天是2002年4月7号,再过三天就是王小波的忌日了,不知道有多少人还会记得这个日子,还会记得这个人。本文的最后,我向大家推荐小波的作品??每一个心智成熟的人都应该读一读小波的文字。在他的杂文随笔集《沉默的大多数》中有一句话谈到了他作为程序员的一面:
“今晚不把这段c++调通,老子就不睡了!”


>>>未完,待续...


 

中国最大的web开发资源网站及技术社区,
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表