C#学习笔记(四)

原创 2002年04月09日 08:53:00

written by cash (天下第七)
2002.04.07
版权所有,翻录不究
cashcao@msn.com

约定

//一个典型的用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.NET/Framework/v1.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++调通,老子就不睡了!”

 

>>>未完,待续...

Oracle学习笔记(四)——上机练习一

1、define命令可以用于定义哪种变量 a、number b、char c、varchar2 d、date 【b】 Host变量主要作用是起到一个替代变量的作用,是主机环境可以和...
  • shangqing1123
  • shangqing1123
  • 2016年04月06日 20:55
  • 609

Unity3D基础篇----Shader学习笔记(4)

这一篇,我们来继续学习Shader中纹理的添加以及实现纹理中凹凸的映射。
  • qq_30501909
  • qq_30501909
  • 2017年06月28日 21:56
  • 269

Oracle学习笔记(4)------------简单查询

学习Oracle感觉有点吃力,于是到网上找了一些学习线路,来有规律的学习,效率能高一些,分享给大家 Concepts                        |                 ...
  • u011225629
  • u011225629
  • 2015年05月26日 12:37
  • 1189

Shader学习笔记4

前两篇写的大多是表面着色器(SurfaceShader),有官方的,网上的,自己写的。自己看着都乱,当做仓库用吧。。。 然后就研究到了顶点和片段着色器,发现很自由,功能很多,但是不能处理光照。还有屏...
  • zzw8866755
  • zzw8866755
  • 2016年09月29日 20:02
  • 160

Nodejs学习笔记(四)

Nodejs用async来处理异步问题: 今天在写mysql数据库操作的时候,发现当我要查询多条sql语句的时候 前一条的语句在后一条语句执行完的时候还没有完成,这个导致很多语句的返回值都是unde...
  • zgq398749824
  • zgq398749824
  • 2016年05月31日 13:54
  • 126

TensorFlow入门(四)——MNIST入门

Softmax回归介绍 softmax回归(softmax regression)分两步:第一步为了得到一张给定图片属于某个特定数字类的证据(evidence),我们对图片像素值进行加权求和。如果这...
  • PinkRiverside
  • PinkRiverside
  • 2017年06月11日 14:08
  • 318

Python学习笔记(5)-多重继承的坑

之前学习了下多重继承,以为领悟到了,没想到实际在项目中傻眼了。 忘了一个关键的地方: 正文 首先得说明的是,Python的类分为经典类 和 新式类 经典类是python2.2之前的...
  • cq361106306
  • cq361106306
  • 2015年01月27日 18:16
  • 810

python学习——多重继承

继承是面向对象编程的一个重要的方式,因为通过继承,子类就可以扩展父类的功能。 回忆一下Animal类层次的设计,假设我们要实现以下4种动物: Dog - 狗狗;Bat - 蝙蝠;Parro...
  • youzhouliu
  • youzhouliu
  • 2016年07月14日 08:32
  • 343

Linux netfilter 学习笔记 之四 ip层netfilter的table注册及规则的添加

既然我们都已经将xt_table、rule、match、target的结构体之间的联系都已经分析清楚了,那我们接下来分析表的注册、表中规则的添加、表中规则的删除、表中规则的替换也应该比较容易了。  ...
  • lickylin
  • lickylin
  • 2014年06月22日 19:02
  • 3341

ETL学习笔记之四:开源项目 Kettle

    现在是一个Google的时代,而对于开发者,开源已成为最重要的参考书。对于某课题,不管你是深入研究还是初窥门径。估且google一把,勾一勾同行的成就,你必会获益良多。    说到ETL开源项...
  • tiger119
  • tiger119
  • 2007年01月21日 09:46
  • 8320
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C#学习笔记(四)
举报原因:
原因补充:

(最多只允许输入30个字)