C#3.0语言详解之基本的语言增强

来源:lover_p.cstc.net.cn  作者:lover_p
C#3.0语言详解之基本的语言增强
摘要:Linq项目简介和开发环境的搭建9月份,微软推出了一项名为“Linq项目”的新技术,用于在.NET语言中集成数据查询的功能。您可以从http://msdn.microsoft.com/netframework/future/得到 Linq项……

Linq项目简介和开发环境的搭建

9月份,微软推出了一项名为“Linq项目”的新技术,用于在.NET语言中集成数据查询的功能。您可以从http://msdn.microsoft.com/netframework/future/得到 Linq项目的技术预览版,其中包括大量的介绍文章(英文)和C# 3.0以及VB 9.0的编译器。

Linq项目英文全称为 Language Integrated Query,即“语言集成查询”。Linq基于.NET Framework 2.0,通过对语言的改进,实现在直接在语言中通过类似SQL语句的构造对数据源进行查询,可查询的数据源从基本的顺序结构(如数组和链表)延伸到关系型数据库(目前是SQL Server,相信将来可以扩展到几乎所有的关系型数据库)和XML。

C# 3.0是C#语言再一次升级后的版本,率先实现了Linq的概念;同样实现了Linq的还有VB 9.0。从上面提到的网址,读者可以找到两种语言的编译器的技术预览版。在本文中我们将以C# 3.0为中心讨论其开发环境的搭建和语言改进。下载得到的是一个名为“linq preview.msi”(也可能不同)的安装包,双击之后可以和其他软件一样进行安装,此处不再赘述。该安装包为Visual Studio 2005 Beta 2及以后的版本和Visual C# 2005 Beta 2提供了插件(项目模板)和C#编译器,该编译器生成的IL代码可以直接在.NET Framework 2.0上运行。在安装了该预览版后,在新建项目对话框中项目类型列表的Visual C#节点下,我们可以看到一个Linq Preview的条目,并可以在右边的项目模板中选择一些桌面项目模板(Linq暂时还不支持Web项目),如下图所示:

图1 - 安装完Linq的Visual Studio 2005 新建项目对话框

只要选中了Linq中的项目模板,我们就可以像编写其他应用程序一样在Visual Studio 2005中开始编写C# 3.0应用程序了,在编译的时候IDE会自动为我们选择C# 3.0的编译器。

现在我们已经可以开始编写C# 3.0应用程序了,后面的章节中我就将为大家讲解C# 3.0所带来的语言增强。值得说明的一点是,本文是一个系列文章中的一篇,这一系列文章共三个部分。本文为第一部分,讲述C# 3.0种基本的语言增强,这些语言增强其实是其他两个部分的基础;第二部分将讲述C# 3.0中的Lambda表达式,这是匿名方法的自然进化形式,它不仅能将表达式体现为可执行的方法(委托),也能将表达式体现为可以在运行时进行操作的数据结构——表达式树;最后一部分讲述的才是Linq项目中最核心的也是最激动人心的内容——查询表达式,这是Linq在C#中的实现形式。同时,Linq 还针对SQL查询和XML查询对.NET Framework基础类库进行了扩充,分别称作DLinq和XLinq,这些内容我将在其他系列文章中为大家讲述。

在本文的讲述过程中,限于篇幅,仅提供了简短的代码段而不是完整的代码。不过这些代码段是从完整的、可正确编译和运行的代码中抽取出来的,这些完整代码可以从这里下载,并且在本文的第5部分中有关于完整代码的介绍。

好了,废话太多了,让我们赶快进入C# 3.0的精彩世界。

具有隐式类型的声明

在一个带有初始化器的声明语句中,待声明的变量的类型是显而易见的——和初始化表达式的结果类型一致。对于这种情况,在C# 3.0中可以使用新增的关键字var来代替声明中的类型,而由编译器根据初始化表达式来推断出变量的类型。

var i = 5; // int
var d = 9.0; // double
var s = "Hello"; // string
var a = new int[] { 1, 2, 3, 4, 5 }; // int[]

Console.WriteLine("Type of variable <i>: {0}", i.GetType());
Console.WriteLine("Type of variable <d>: {0}", d.GetType());
Console.WriteLine("Type of variable <s>: {0}", s.GetType());
Console.WriteLine("Type of variable <a>: {0}", a.GetType());

上面的代码在C# 3.0中是符合语法规则的,前四行代码就是使用了隐式类型的声明;而后四行代码用于在运行时验证各个变量是否拥有正确的类型。如果在Visual Studio 2005中运行这段代码(为了能够看到结果,请使用Ctrl+F5来编译并启动程序),会得到下面的结果:

Type of variable <i>: System.Int32
Type of variable <d>: System.Double
Type of variable <s>: System.String
Type of variable <a>: System.Int32[]

这表明,编译器在编译的时候,已经正确地推断了每个变量的类型,并将其嵌入到了程序集的元数据中。

这里有两个限制,一是具有隐式类型的声明只能作用在局部变量上,二是这种声明必须有初始化器(即等号和后面的表达式)。如果我们企图在一个类中声明一个具有隐式类型的域,就会出现一个编译错误:Invalid token ’var’ in class, struct, or interface member declaration;而如果声明中没有出现初始化器,则会导致另外一个编译错误:’=’ expected。

除了局部变量外,作用域为一个块的数组也可以运用具有隐式类型的声明,例如:

var ia = new [] { 1, 2, 3, 4, 5 }; // int[]
var da = new [] { 1.1, 2, 3, 4, 5 }; // double[]
var sa = new [] { "Hello", "World" }; // string[]

Console.WriteLine("Type of array <ia>: {0}", ia.GetType());
Console.WriteLine("Type of array <da>: {0}", da.GetType());
Console.WriteLine("Type of array <sa>: {0}", sa.GetType());

在上面例子的数组声明中,在运算符new和表示数组声明的一对方括号之间省略了类型名字,但这在C# 3.0中仍然是符合语法规则的。编译器会通过成员列表中的值的类型来推断数组的类型。编译并运行上面的例子,会得到如下的输出:

Type of array <ia>: System.Int32[]
Type of array <da>: System.Double[]
Type of array <sa>: System.String[]

除了和具有隐式类型的局部变量具有相同的约束外,具有隐式类型的数组还有必须尊从这样一个规则,即成员列表中的所有值必须是兼容的。也就是说,成员列表中必须存在这样一个值,使得其他值可以隐式地转换为该值的类型。因此,下面的声明是不符合语法规则的:

var aa = new [] { 1, "Hello", 2.0, "World" };

如果试图编译上面的代码,会得到一个编译错误:No array type can be inferred from the initializers。这是因为编译器无法根据成员列表中的值来推断数组的类型。

实际上,尽管具有隐式类型的声明使得传统声明的编写方法更加便利,然而引入这种声明方式的真正目的并不在于此,而是为了使局部变量和数组能够访问这样一个新的语言构造:匿名类型。

【相关文章】好搜一下
基于ASP.NET的自定义分页显示

基于ASP.NET的自定义分页显示

摘要:本文针对WEB数据库记录的显示问题,用实例讨论了在ASP.NET框架下使用…