代码改变世界

为什么在VS2010中编写.net 2.0程序可以调用C#2.0以上版本特性?

2013-04-07 02:30  Desmond  阅读(3445)  评论(1编辑  收藏  举报

公司的程序一般使用会使用.Net 2.0,在使用VS2010编写程序后,发现使用了一些C#3.0,C#4.0特性后,程序居然也可以正常运行,对此一直有点迷惑,最近花了点时间仔细研究了一下。

在讨论为什么VS2010会出现这种情况之前,先引入几个概念,我们重新认识一下。

201206171833245048

C#版本与C#编译器

C#源代码要编译成IL中间语言,需要调用C#编译器。C#编译器其实是一个名为csc.exe的可执行文件,通常位于系统目录下的 Microsoft.NET\Framework\<version> 文件夹中,version指的是.Net的版本,我的电脑中装有VS2005 VS2008 VS2010时,里面有v1.0 、v1.1 、v2.0、 v3.0、 v3.5、 v4.0几个版本。经过查看,我发现v2.0 、v3.5、 v4.0里面含有csc.exe文件,而这正好和C#的版本是对应的。不难想到,不同版本C#编译器代表编译过程中遵循不同C#版本的语法

现在回到我们的问题:VS2010中.Net2.0工程可以使用C#2.0版本以上的特性。初步可以怀疑VS2010编译时调用的是4.0版本的C#编译器,而不是2.0版本的C#编译器。

下面实际编译一段代码来试验一下。这段代码在VS2010生成是可以通过的。

class Program
    {
        static void Main(string[] args)
        {
            ///隐式类型变量 (C#3.0特性)
              var i = 0;
            Console.WriteLine(i.ToString());
            Console.ReadKey();
        }
    }

使用2.0的C#编译器,编译失败

image

使用4.0的C#编译器,编译成功

image

VS2010直接生成得到的ConsoleApplication2.exe,我使用C#编译器自己生成的是Test.exe文件。现在,我发现两个文件有一点不相同。他们引用的mscorlib.dll版本不同。

imageimage

其实,在设置项目工程的.Net Framework版本时,就是设置C#编译器编译时调用对应版本的mscorlib.dll文件。(mscorlib.dll到底代表什么,可以查阅CTS BFL等概念)

虽然现在两个exe文件中的引用不同,但是我们可以手工调用对应版本的mscorlib.dll文件,重新生成一个exe文件。(/nostdlib 禁止导入定义整个 System 命名空间的 mscorlib.dll,也就是4.0的mscorlib.dll)

imageimage

通过以上实验,可以说明VS2010调用了4.0版本的C#编译器。

C#特性的实现

VS2010调用了4.0版本的C#编译器成功编译了.Net 2.0工程的源代码,说明C#源代码成功编译成IL中间语言代码。但是C#2.0版本以上的特征为什么可以成功编译,还没有明白。

C#是高级语言,IL是相对C#低级一些。C#特性在实现上要依赖IL特性。在此我能想到的C#特性的实现有两种(关于什么才能称为特性,我暂且认为这个版本新增的就为这个版本的特性):

  1. 直接是IL特性的实现。比如private 关键字,可以适应Reflector查看IL代码,里面就有private关键字。这种实现方式不需要调用其他的资源如dll程序集。
  2. 结合或者直接就是.Net 版本的另一种实现方式,需要依靠mscorlib.dll或者其他程序集。比如lock关键字,封装了Monitor线程处理方法,是一种语法糖。这种特性,没有相应的dll是不能调用的。

那么由此C#2.0以上版本的特性,如果属于第一种情况,那么Net2.0工程中使用是没有问题的。如果属于第二种情况,那么需要mscorlib.dll为2.0版本,.Net2.0工程才可以能使用。

经过实验总结:以下特性是可以使用的

  1. 对象初始化器
  2. 集合初始化器
  3. 自动属性
  4. 隐式类型变量
  5. 隐式类型数组
  6. 匿名类型
  7. lamda表达式
  8. 可选参数(4.0):其实.Net 2.0版本中 VB语言就实现了可续参数。

总结

有高版本的C#编译器,就可以使用C#高版本的特性。能用的特性尽情的用,不能用的特性会报错误,自然也就无法用了。

为什么在VS2010中编写.net 2.0程序可以调用C#2.0以上版本特性?其实从这个问题中,便可以发现我将.Net版本与C#版本的概念混淆了。这句话应该这样,在VS2010开发环境下,使用的是4.0版本的C#编译器,如果创建.Net 2.0项目,可以使用C#4.0中任何不依赖.Net和仅依赖于.Net 2.0的C#特性

 

本文写的十分浅薄,请结合一下两篇文章阅读,会更清楚一些。

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

http://www.cnblogs.com/PurpleCow/archive/2012/06/17/2552780.html