.net框架

时间:2023-03-09 21:18:48
.net框架

转载:http://www.cnblogs.com/JimmyZhang/archive/2012/11/27/2790759.html

本书是一本讲解.NET技术的书籍,目标读者群也是在.NET框架(.NET Framework)下进行开发的程序员,因此我们无法回避的问题就是:什么是.NET框架?它包含了哪些内容?为开发程序提供了哪些支持?很多朋友对这类个问题的第一反应可能是.NET框架所提供的庞大类库及编写代码所采用的C#语言,实际上远不止这些。

要描述.NET框架,自然会遇到与其相关的一系列专业的技术术语和缩写,相信大家已经见到过许多了,比如:CLI、CIL、CTS、CLS、CLR、JIT、BCL、FCL、Module、Assembly 等,足以让很多人一头雾水、望而却步。笔者不会像字典一样按首字母排序对术语进行逐一解释,因为这样还是难以理解。我们还是从大家最熟悉的东西开始吧!

6.1 引子

设想一下:编写下面这样一个最简单的显示“Hello, World!”的控制台程序,并将该程序运行起来需要哪几个步骤呢?

using System;
 
class Program {
    static void Main(string[] args) {
        string text = "hello, world!";
        Console.WriteLine(text);
    }
}

这些步骤包括:打开Visual Studio,创建一个C#控制台应用程序项目(在这里将它命名为ConsoleApp),编写代码,编译程序然后运行。这样的程序谁都会写,但是再多进行一下思考就会发现,尽管是一个很小的程序,但已经引入了.NET框架的几个重要方面。

如果创建一个VB.NET类型的项目,实现和上面C#项目完全一样的功能,那么编译后生成的文件有什么区别?

编写控制台应用程序,将字符输出到屏幕,需要调用Console.WriteLine()方法。这个Console类型从何而来呢?

生成的文件在系统中是如何运行起来的?其机制和使用传统VC++生成的可执行文件是否相同?

其实,上面每一个问题的答案都包含.NET框架所提供的支持,这里将它分为三个部分:

  • 对于编译后生成的文件格式和内容,.NET中存在着诸多规范。符合这些规范的程序语言,也叫做面向.NET的语言。编译后生成的文件都可以在.NET运行时下执行,这就是大家所熟知的.NET多语言支持。
  • 在开发阶段,.NET提供了一个庞大的类库,支持开发者快速开发各种应用程序,也支持程序语言设计者开发其语言编译器。
  • 在程序执行阶段,.NET提供了一个程序运行时的环境,这个运行时环境帮助我们管理内存、实时编译程序、进行安全检查、执行垃圾回收等。

接下来就针对上述内容开始为大家详细讲述。

6.2 CIL——公共中间语言

首先要了解的就是C#程序源码在编译之后会得到什么样的一个文件。大家知道,过去使用VC++生成的可执行文件,经过预编译、编译、汇编、链接几个步骤后,最终生成的可执行文件中就已经包含了处理器的本地代码(Native Code),支持它运行的只是操作系统和本地的机器指令集。那么采用C#编译器生成的文件又是什么呢?现在需要引入程序集这个概念:在.NET框架下,类似C#这样的高级语言经过编译后生成的结果文件被称做程序集,其后缀名是.dll(类库)或.exe(可执行程序)。在引入这个概念之前,前面(上一节)提到程序集时,都是用“文件”这个词来描述的。

程序集的定义只是给编译后生成的文件一个稍微正式一点的名称,对于解释“它是由什么构成的”这个问题并没有太大的帮助。为了进一步了解程序集,我们再来做一个试验,使用VB.NET创建一个控制台应用程序项目(ConsoleAppVB),并生成一个程序集,代码功能和上面用C#创建的项目是一样的的。

Module Program
Sub Main()
Dim text AsString = "hello, world !"
        Console.WriteLine(text)
EndSub
EndModule

现在,需要一个工具来查看这个程序集的内容,并且与C#项目生成的程序集进行对比。还好,微软已经提供了一个利器——IL DASM(IL Disassembler,IL反汇编程序)来帮助开发者查看程序集的信息。如果安装了Visual Studio,IL DASM将会随同Visual Studio一起安装。依次选择开始菜单→ Microsoft Visual Studio 2010 → Microsoft Windows SDK Tools →IL 反汇编程序(IL DASM)可以启动IL DASM。

打开IL DASM后选择VB.NET项目生成的ConsoleAppVB.exe,可以看到如图6-1所示的界面。

.net框架

图6-1 IL DASM 运行界面

这部分内容很多,会在下一章“程序集”中进行专门讲述,,这里暂且略过。展开图6-1中的ConsoleAppVB.Program类型,在Main()方法上双击,会弹出另外一个窗口,显示图6-2中的代码,看上去有点像汇编语言。在这里可以看到熟悉的string text变量声明及“hello, world !”。

.net框架

图6-2 方法体的CIL语言描述(VB.NET)

接下来再打开C#项目生成的ConsoleApp.exe,进行同样的操作,在打开Main()方法后会发现其中的代码与图6-2中几乎完全一样,如图6-3所示

.net框架

图6-3方法体的CIL语言描述(C#)

至此,可以得到一个初步的推断:不管是VB.NET还是是C#,编译之后的程序集都能够用IL DASM打开,因此它们生成的程序集的格式都是相同的;当程序所实现的功能相同时,程序集所包含的CIL代码也是类似的。

现在对上面程序集中所包含的类似汇编的语言做一下介绍,即是本节标题中的CIL(Common Intermediate Language,公共中间语言)。CIL最初是随着.NET由微软一起发布的,因此之前也叫做MSIL(Microsoft Intermediate Language),后来进行了标准化,之后便被称做CIL。在一些书或文章中,CIL也会简写为IL,其实都是指同样的东西。为了避免混淆,本书统一用CIL这个缩写。

我们可以将上面的过程用图6-4来表示出来。

.net框架

图6-4 源程序编译为了程序集

接下来再深入地分析一下,公共中间语言这个术语到底包含了哪几层含义。

  • 公共。因为不论是C#语言也好,VB.NET语言也好,C++/CLI语言也好,甚至是重新开发的一套以自己的名字缩写命名的语言,只要它期望运行的目标平台是.NET,在经过相应的编译器编译之后,所生成的程序集就是由CIL语言代码描述的。
  • 中间。这个词也是大有深意,为什么不叫公共机器语言(Common Machine Language),或者公共本地语言(Common Native Language)?因为这种语言只是比我们使用的高级语言,比如C#低级一点,并不是CPU可以直接执行的本地机器语言。这种语言还需要.NET运行时(.Net runtime)环境的支持,在执行之前,进行一个被称为Just-in-time(即时)的二次编译过程,才能转变成计算机可以识别的指令。关于.NET运行时,以及详细过程后面再介绍,现在只要知道,这个文件所包含的CIL代码并非机器可以直接执行的指令代码。
  • 语言。CIL不过是一种程序语言,只不过相对于C#来说,它是一种更低级语言。从图6-2 的代码截图中,已经可以看到,CIL是一种基于堆栈的语言,同时,它提供了class、interface、继承、多态等诸多面向对象的语言特性,因此它又是完全面向对象的语言。如果愿意,甚至可以直接编写CIL代码,并且使用CIL的编译工具IL ASM(IL Assembler,IL汇编程序)来对它进行编译。只不过,和大多数低级语言一样,这种方式会使开发效率会变得很低。这里注意区别一下IL ASM和IL DASM,它们的拼写是不同的。

为了加深一下印象,我们来做一个试验:编写一段简单的CIL代码,并且使用IL ASM工具对其进行编译,得到和前面一样的ConsoleApp.exe程序。

1)打开记事本程序,输入下面的代码,然后将其保存在D:\ConsoleApp.il。

.assembly extern mscorlib{}
.assembly ConsoleApp{}
.module ConsoleApp.exe
.class public auto ansi Program extends System.Object
{
    .method public static void Main()
    {
        .entrypoint
        nop
        ldstr "Hello, World!"
        call void [mscorlib]System.Console::WriteLine(string)
        nop
        ret
    }
}

2)打开Visual Studio 2010命令行工具,输入:

D:\>ilasm ConsoleApp.il

3)成功后会看到ConsoleApp.exe程序,它的执行结果和上面用C#编写的完全一样。

由于程序集是由CIL语言所描述的,因此CIL也叫做程序集语言(Assembly Language)。又因为.NET程序集需要由.NET运行时加载才能运行,可以视其为由.NET运行时进行管理的,所以CIL代码也叫做托管代码(Managed Code)。相对的,不需要.NET运行时就可以执行的代码就叫做非托管代码(Unmanaged Code)。

好了,已经知道了CIL的存在,从现在开始,最好在头脑里建立起两个模型或两种视角:一种是基于C#或其他高级语言的源程序的视角,一种是基于CIL中间语言的程序集视角。C#源程序在被编译为程序集以后,就独立于C#,因此程序集可以由其他种类的语言所调用;同时,因为程序集并没有包含本地机器的指令,所以它与具体的机器类型也分隔开了,可以被装有.NET框架的任何机器运行。