本节书摘来自异步社区《圣殿祭司的asp.net4.0专家技术手册》一书中的第2章,第7节,作者: 奚江华,译者: 武海军 , 更多章节内容可以访问云栖社区“异步社区”公众号查看。
圣殿祭司的asp.net4.0专家技术手册
以var声明的类型,叫做“隐含类型声明”,像传统javascrip一样以var声明变量或对象。
以下用var隐含类型声明数值及字符串的方式:
var隐含类型声明创造的最大目的是,为了配合linq查询语法与匿名类型(anonymous type)的特性,因为很多时候在声明linq查询匿名类型时,使用var关键字来声明类型,可让语法变得十分精简,而不必为了类型的指定而花太多力气。
var隐含类型声明常应用在:①隐含类型局部变量、②隐含类型数组、③匿名类型对象,如图2-4所示,后续将详述这3种应用。

附注 当然隐含类型可接受的类型还更多,在这仅介绍比较常用的,在2-6-5小节列出其他隐含类型。
隐含类型局部变量(implicitly typed local variables),顾名思义,就是利用var在一个区域(指方法)中声明隐含类型的变量。
范例2-2 基本var隐含类型局部变量声明
在此以var关键字声明隐含类型局部变量,并进行加法运算,请参考varvarible.aspx程序:
程序说明
a+b运算的结果是15。但勿将var的声明语法搬到.net 1.0或2.0环境中使用,因为不支持。
var除了声明局部变量外,也可用来声明隐含类型数组(implicitly typed arrays)。隐含类型数组是通过new[]关键字来声明。以下说明传统数组与隐含类型数组语法上的差异。
1.int类型数组语法
以下为传统int类型数组与隐含类型数组的差异,其中隐含类型数组声明,完全不需指定int类型,而其类型是由数组元素(element)推断而来(编译器会进行类型推论与判断)。
2.string类型数组语法
以下为传统string类型数组与隐含类型数组的差异。
程序:arraysample.aspx 隐含类型数组声明
3.不规则数组语法
以下为传统int类型不规则数组与隐含类型不规则数组的差异。
范例2-3 隐含类型数组的定义与linq查询运用
前面var程序中,隐含类型数组在声明上没有太大难处,但其实查询与运用才是重点,因此,在此要探讨隐含类型数组与传统语法在查询上的差异,且使用linq来查询数组的数据。在此以汽车销售为例,请参考impilicityarray.aspx程序:
..iconn01.tif 若是单纯对数组内容的读取,可使用传统的for,若以var声明的linq查询表达式,则可用foreach来读取。
..iconn02.tif 至于foreach中,类型的声明可用var或int明确类型。
..iconn03.tif 隐含类型数组声明好之后,可用linq进行查询(选择性,非必要),进行条件的筛选。
程序的执行结果如图2-5所示。
1级提醒
隐含类型只支持一维的数组,不支持多维的。
当使用匿名类型对象时,有很高的几率搭配var隐含类型,因为匿名类型对象只能指定给var所声明隐含类型。var创造的最大的目的是,为了配合匿名类型语法。
范例2-4 匿名类型搭配var隐含类型声明
以下匿名类型中是个人基本数据,然后再赋值给var隐含类型的person对象,请参考varanonymous.aspx程序:
..iconn01.tif 第3行程序中以var声明了一个匿名类型对象,里面同时包含了string字符串与int数值,请问我们该叫person为什么类型呢?
..iconn02.tif 若c# 3.0不发明“var”隐含类型声明,坦白讲person这样的匿名类型对象根本无法直接用一种类型对应。
..iconn03.tif 但就算var属于隐含类型声明,也不表示所声明的对象或变量没有类型,只是无法刻意用一个确定类型名称来描述它,故统称匿名类型。
..iconn04.tif 程序在编译时,会为person这个anonymous type对象私下取一个名字,叫做“<>f__anonymoustype0'3[system.string, system.int32,system.int32]”,它的名字中带有anonymoustype字眼,而且类型确定的强类型对象,而不是没有名字、没有类型的未知对象,用gettype()方法就能查知。有点像老子《道德经》中所说:“道本无名,强名曰道”的意思,系统很清楚这个对象名字与类型,但不好用人类懂的术语来讲(如string或int),但人类又强要个名字,故只好弄个假名“anonymoustype”,好让你不再困惑。
程序执行结果如图2-6所示。
但var隐含类型的本质,完全不是javascript的var变量声明那回事,若你以为两者是同一特性就大错特错了。c# 3.0只不过借用var避开了一开始某些类型声明上的困难,以增加灵活性,但骨子里却仍然是静态语言及强类型的坚持者,和javascript的var声明完全不同,以下是说明:
类型确定时期:var在编译时就确定了类型,但javascript要在运行时才会知道类型,这对程序质量与稳定性有很大影响。
类型推论:以var所声明的变量或数组,其类型之所以能确定,是因为var会指示编译器去推论变量或对象正确类型,而推论的基础在于“=”等号右方的表示式类型,例如,var a=123,则编译器就会将a视为int类型,若var a=“kevin”,自然a就是string类型了。
类型变更限制:从.net 1.0开始,一旦声明类型后,类型就无法在运行时任意更换,即使使用了var声明,但编译后的类型早已确定,运行时一样不允许更换类型,例如,声明了var a =123,a就是int类型,不能再动态指定a =“kevin”,编译程序会警告错误;但javascript以var声明的变量类型,可以在运行时任意改变类型,没有限制。
类型:var能接受或声明的类型有.net framework系统内建类型、.net framework class library中定义的类型、anonymous type类型、用户自定义类型(user-defined)或其他任何的表示式。
与linq搭配:linq查询常会搭配var声明。
1.var声明使用范围
使用“var”关键字声明变量或对象,范围是有限制的:
只能在方法层级中使用,声明局部变量,不能在类层级中声明为全局变量;
在for的语句中使用,如for(var x = 0; x < 50; x++){…};
在foreach的语句中使用,如foreach(var item in list){...};
using (var file = new streamreader("c:myfile.txt")) {...}。
2.var声明错误示范
以下var为不合法的例子。
程序:varclass.cs var不合法声明例子
所以看到var种种限制后,应能了解var的运用倾向于配合c# 3.0新语法功能的灵活性运用,而不是用来全面替代明确类型的声明。
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。