您的位置:首页 > 编程语言 > C#

C#2008语言特征1---隐含类型本地变量

2009-03-21 12:33 176 查看
最近,微软在C#规范方面动作十分的迅速,在C#2.0规范推出不久,还没有让很多人熟悉其新的特点,很快又推出了C#3.0规范。随着新版本的推出,又增加了很多的新的特征。大家对新的特征评价不一。有的人对新特性的推出兴奋不已,感叹微软实力的雄厚以及在语言方面新思想的超前。另外一部分人认为新特性在不断的破坏完全面向对象的思想,让.Net框架下面的语言变得越来越臃肿,越来越复杂难用,这些新的特性有的甚至动摇了一些思想的根本。
究竟这些新的特征如何?还是需要程序员本身去真实的感受,也许有些特点你会发现是你梦寐以求的,也许你觉得不过如此而已。那么这些新的特征有那些呢?这些新的特征主要包含隐含类型本地变量(implicitly typed local variable declaration)、自动属性(Automatic Properties)、扩展方法(Extension Methods)、局部方法(Partial Method)、对象初始化器(Object Initializers)、匿名类型(Anonymous Type)等。
本节主要针对上面的一些特征,根据具体的实例来讲解,同时尽量解析这些新的特征的实现技术与本质。
9.1隐含类型本地变量
C#语言是一种强类型的语言,以前在声明变量的同时,必须显式指出该变量的类型,否则将会出现编译错误,从C#3.0开始,在声明一个变量的同时,可以不具体说明该变量的类型,而可以声明为var类型。
很多有经验的程序员可能一眼就认出这个“var”是JavaScript的,这个变量在JavaScript中可以保存任何数据类型的数据,相当于是一个变体类型,也就是这个类型会随着存储数据的不同而自动改变类型,但是同时也带来了程序的不安全等因素,还有最大的是性能方面的损失。微软在C#3.0中的“var”是不是跟JavaScript的中的含义相同呢?下面看一个具体的实例ImplicitlyLocalVar。
namespace ImplicitlyLocalVar
{
class Program
{
static void Main(string[] args)
{
var Iint = 3;
var Ddouble = 5.9;
var Ffloat = 5.6f;
var Sstring = "我使用c#编程。";
var IintArray = new int[3] { 4,5,6 };
Console.WriteLine("{0}是-------{1}",Iint,Iint.GetType());
Console.WriteLine("{0}是-------{1}", Ddouble, Ddouble.GetType());
Console.WriteLine("{0}是-------{1}", Ffloat, Ffloat.GetType());
Console.WriteLine("{0}是-------{1}", Sstring, Sstring.GetType());
foreach (var temp in IintArray)
Console.WriteLine("{0}是-------{1}", temp, temp.GetType());
Console.ReadKey();
}
}
}
在上面的程序中声明了很对的变量,但是没有一个变量显式的声明变量的具体类型,最后使用变量的GetType方法打印出具体的类型。程序运行的结果是:



从运行结果可以看出,每一个变量在运行是都知道自己属于那个具体的类型,而不是像JavaScript那样采用了变体类型的概念,下面在看一下使用Reflector工具反编译的代码。
图9-1是反编译的代码。



图9-1
从反编译以后的代码可以看出,编译器在编译代码的时候已经根据变量初始的值自动将var类型替换为具体的类型了,所以从这一点来说,c#中的var与JavaScript的完全不同。
因为c#在编译代码的时候,要根据var变量的初始值来确定它的类型,所以有一定的约束规则,这些规则如下:
1)声明者必须包含一个构造者。
这个构造者必须是一个表达式。这个构造者不能够是一个对象或者构造者集合的自身,但是它可以是一个新的包含一个对象或者构造者集合的表达式。
2)在编译时刻构造者表达式的类型不能为null类型。
3)如果本地变量声明包含多种声明者,那么构造者必须都具有相同的编译时刻类型。
根据规则,下面就是一些错误的使用var的情况。
var x; //错误,因为没有给变量初始值
var y={1,2,3}; //错误,集合不能被初始化
var z=null; //错误,初始化的值不能是null
关键字 var 只能在本地范围内使用。换句话说,可以用这种方式去定义本地的变量,可是成员或者参数却不能。
比如用法
class VarDemo {
// 变量作为类,接口的成员变量
var k =0;
// var类型的变量不能作为方法或者函数的参数
public void InvalidUseParameter( var x ){}
// var类型的变量不能作为方法或者函数的返回值
public var InvalidUseResult() {
return 2;
}
k 的类型能从常量初始化器中推断,但是var不允许作为成员的类型。 InvalidUseResult 返回值的类型虽然可以从内部的return语句声明中推断出来,但这种用法依然是不允许的。
虽然这样简化了代码编写,但是它降低了代码的可读性。例如,您调用一个重载方法,而方法的各个版本仅是参数类型不同,阅读这代码将不清楚哪个版本的方法被调用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: