2-10 匿名类型
圣殿祭司的ASP.NET4.0专家技术手册
C# 2.0有匿名方法(Anonymous Method),而C# 3.0又新增了“匿名类型(Anonymous Types)”,它的目的是“提供一个简单的途径将一组只读的属性封装在一个对象之中”,且在第一时间不必声明其明确类型。
2-10-1 匿名类型的由来
以下是一段匿名类型的变量声明,并以new的关键字进行初始化:
为什么要叫“匿名类型”?原因有几个:
(1)传统多半是先建立一个具名(Named)的类,然后再实体化一个类对象,因此,这个类一开始就有明确的名称定义;而“匿名类型”对象,从头到尾根本未指定过任何的名称,故称“匿名”。
(2)因为以匿名类型方式声明的对象,无法事先确定类型,必须等到编译器编译后,类型才是确定的,所以对程序员而言,类型是隐匿的。
(3)即使类型在编译后确定下来,也只有编译器及系统本身内部知道,就连在Visual Studio的Debug模式中,也一样无法得知确切类型,故执行或Debug除错时,对程序员还是隐匿的。
(4)对于以匿名类型方式声明的对象,关于类型及名称的部分,类型是由编译程序自行推论而决定,名称也是当下命名的,故一如先前所讲“道本无名,强名曰道。”原本这对象是没有具体的名称和类型,遇见了编译器这个“识人之士”,才给定“Anonymous Type”的名称和类型。
(5)在原本的.NET Framework之中,一个对象或变量就是单一类型,但匿名类型的变量,里面可能同时包含了string及int类型的属性,请问该叫它string类型,还是int类型?由于没有直接对应的类型,再加上它是多个类型的混合体,无法归属任何一个类型,最好的方式就是自成一格,就叫做“匿名类型”。
所以由上可知,匿名类型对象在主客观情形下,都是一再地“隐姓埋名”,一再地藏匿其明确类型,故称为匿名类型恰如其分,如图2-8所示。
“匿名类型”一词虽然有隐匿名称与类型的特性,但可别真以为它是没有类型的!一如老板常挂在嘴边的话:“我本身是开明的、我本身是没有默认立场的。”看到这里大家心里都会偷笑,做员工的只能口头上连连称是,但没人会信以为真,因为多半项目或决策最终仍是由老板的偏好与立场所左右,要真的弄不清老板的喜好,那可真完了。所以有些事情只是表面上形势不强,但骨子里却是出奇的强,故别被“匿名类型”表面字义的错觉给误导了,以为它是没类型或类型不明确的,以下是匿名类型的特性说明:
类型确定:所以别误以为匿名类型没有类型,它有明确的类型,事前虽不知类型,但编译后类型就确定了。
属性只读:匿名类型对象内的属性是只读的,不可更改,否则在编译时就会产生错误。
使用new关键字:匿名类型对象的初始化是使用new关键字。
类类型:匿名类型对象是属于Class类型,并且其类型是由其内部多个不同属性类型所组成。
类限制:匿名类型对象虽属于Class类型,但是其中不可以声明方法或事件等类成员,唯一接受的是属性。
反射类型:匿名类型虽然具有某种程度的隐密性,不让程序员可以直接观察到,但还是可通过Reflection去探索该对象的正确类型。
搭配var:匿名类型对象最常搭配var隐含类型声明,因为二者在声明上,都是对类型不需明确声明的。
搭配LINQ:匿名类型常搭配LINQ的select子句来进行查询。
类型归类:如果有多个匿名类型,其中所声明的属性、数量及顺序都一样的话,则编译器编译程序会自动视它们为相同的类型。
范例2-7 匿名类型对象的建立及使用
匿名类型初始化的对象,常以var声明其类型,两者常进行搭配运用,请参考AnonymousType. aspx程序:
238 protected void Page_Load(object sender, EventArgs e)
239 {
240 //声明一个匿名型对象
241 var person = new { Name = "圣殿祭司", City = "Taipei", Height = 180,
Weight = 75 };
242 //person.Name = "奚江华"; //不合法,匿名类型是Read-Only,不可修改
243 //使用person匿名类型对象
244 string txtMsg = string.Format("姓名:{0},住在:{1},身高:{2},体重:{3}",
person.Name, person.City, person.Height, person.Weight);
245 Response.Write(txtMsg);
246 }
程序说明
由于匿名类型是“提供一个简单的途径将一组只读的属性封装在一个对象之中”,因此属性是只读的。
范例2-8 探索匿名类型对象的类型与名称
既然作者口口声声说匿名类型对象类型是明确的,且编译器在编译时会替对象命名,并决定其类型,那可否进一步说明,如何真实见到其类型呢?请参考AnonymousTypeName.aspx程序:
247 protected void Page_Load(object sender, EventArgs e)
248 {
249 //实例化一个Customer类型对象
250 Customer Mary = new Customer();
251
252 Type t1 = Mary.GetType();
253 Response.Write("Mary的类型是:" + t1. UnderlyingSystemType +
",FullName是:" + t1.FullName+ ",Name是:" + t1.Name + "<BR/><BR/>");
254
255 //声明一个匿名型对象
256 var person = new { Name = "圣殿祭司", City = "Taipei", Height = 180, Weight
= 75 };
257
258 Type t2 = person.GetType();
259 Response.Write("person的类型是:<Font Color='Blue'>" + t2.
UnderlyingSystemType + "</Font><BR/>");
260 Response.Write("person的FullName是:<Font Color='Blue'>" + t2.FullName +
"</Font><BR/>");
261 Response.Write("person的Name是:<Font Color='Blue'>" + t2.Name +
"</Font><BR/>");
262 }
程序说明
为了让匿名类型有个对照,在此建立了Customer类的实体,并显示其类型与名称。
Type t2 = person.GetType()程序则是.NET Reflection技巧,可用来探索对象的属性与方法。
程序运行结果如图2-9所示。
2-10-3 匿名类型在隐含类型数组上的运用
前面在介绍隐含类型数组声明时,数组中的成员多半是int或者是string类型,但其实也可将匿名类型对象当成数组成员,然后加入隐含类型数组中。
范例2-9 匿名类型结合隐含类型数组——以模特经济公司为例
假设有一模特经济公司,要建立模特的基本数据供查询使用,在此以匿名类型建立模特个人资料,并加入隐含类型数组中,最后以LINQ做筛选查询,请参考AnonymousType Array .aspx程序:
程序说明
当然这只是数据建立与查询示范,实际模特基本数据的建立与保存,仍然是以SQL Server数据库为对象最佳。
程序运行结果如图2-10所示。
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。