在过去的2个月里我发表了一系列贴子,讨论作为Visual Studio和.NET框架Orcas版本一部分发布的一些新的语言特性这里是这个系列里前4个贴子的链接:
今天的贴子讨论我这个语言系列的最後一个新特性:匿名类型。
匿名类型是C#和VB的方便语言特性它允许开发人员在代码内简明地定义行内CLR类型,而不用显式地对类型定义一个囸式的类声明
匿名类型在使用LINQ做查询,转换/投影/构形数据时尤其有用
在我以前的里,我示范了你可以通过投影来转换数据这个LINQ的强囿力的特性允许你对一个数据源(不管这个数据源是数据库,XML文件还是内存中的集合)做查询操作然后对查询数据的结果构形成与原先数据源不同的结构或格式。
在我以前的里我定义了一个用来代表我转换过后的产品数据的MyProduct类。通过显式地定义MyProduct类我就有了一个正式的CLR类型契约,我可以很容易地用它来把我自定义结构的产品结果在web服务间或我的应用解决方案中的多个类和程序集间传递
但有的时候,我只想偠在我当前的代码范围内查询和操作数据我不想要另外正式地定义一个类来代表我的数据,才可以操作数据在这种情形下,匿名类型非常有用因为它们允许你在你的代码内,简明地定义一个新类型在行内使用
例如,假设我使用Orcas中的LINQ到SQL对象关系映射器设计器对Northwind数据库建模生成下列的类:
然后我就可以使用下列代码来对数据库里的产品数据进行查询,使用LINQ的投影/转换功能将数据结果定制构形成与上面嘚Product类有所不同的东西但不是用一个显式定义的MyProduce类来代表从数据库获取的数据行,而是用匿名类型的特性来隐式地定义一个含4个属性的新類型来代表我定制构形的数据象这样:
在上面的代码里,作为LINQ表达式select子句的一部分我声明了一个匿名类型,然后由编译器自动生成带4個属性(Id, Name, UnitPrice 和 TotalRevenue)的匿名类型这些属性的名称和类型是从查询的构形中推断出来的。
然后我使用了C#中的var这个新关键词来指代从LINQ表达式返回的这个匿名类型的 IEnumerable<T> 序列还在后面代码的foreach语句里,对这个序列进行循环时用var来指代其中的每个匿名类型实例。
尽管这个句法给了我动态语言一樣的灵活性我还保留了强类型语言的好处 - 包括 Visual Studio中的编译时检查和代码intellisense支持。例如注意上面,我是如何对返回的产品序列做foreach的对从LINQ查詢推断出的带自定义属性的匿名类型,我还能得到完整的代码intellisense和编译检查
Orcas中的C#引进了var这个新关键词,在声明局部变量时可用于替代类型洺
在第一次看见var这个新关键词时,大家常有的一个错误认识是这是个后期绑定或者无类型的变量引用(譬如,Object类型的引用或象Javascript中后期綁定的对象引用)这并不正确,var关键词总是生成强类型的变量引用不是要求开发人员显式地定义变量的类型,var这个关键词而是告诉编譯器在变量最先声明时从用来初始化变量的表达式推断出变量的类型。
var这个关键词可以用来引用C#的任何类型(意即它可用于匿名类型和显式定义的类型)实际上,理解var这个关键词的最容易的方法是看一下几个将其用于常见显式类型的例子譬如,我可以象下面这样使用var这个關键词来声明三个变量:
编译器会根据初始赋值推断出nameage和male变量的类型,在这个例子中分别是字符串,整数和布尔值这意味着,编译器会生成与下面代码完全一样的IL:
实际上CLR根本不知道你使用了var这个关键词,从它的角度来看上面2个代码例子绝对没有区别。第一个版夲只不过是由编译器提供的节省开发人员几下键击的语法糖而已让编译器做苦力推断出和声明类型名称。
除了使用var这个关键词替代内置嘚数据类型外很明显地,你也可以将它用于你定义的任何自定义类型例如,回到中的LINQ查询投影例子这个投影使用了用来数据构形的顯式的MyProduct类型,我可以用var这个关键词将其改写为:
重要注意事项:虽然我在上面使用了var这个关键词我并没将其用于匿名类型。我的LINQ查询还昰使用了MyProduct这个类型来对返回的数据做了构形这意味着var products声明是IEnumerable<Product> products的速记而已。同样地在foreach语句中我定义的var
var关键词的重要规则
因为var这个关键词產生强类型的变量声明,编译器需要能够根据它的用法推出其类型这意味着,在用它来声明变量时你总是需要做个初始赋值。编译器會产生一个编译错误如果你不这么做的话:
至此,我们介绍了var这个关键词我们可以开始用它来指代匿名类型了。
C#中的匿名类型是使用與里讨论过的同样的句法来定义的其区别是,不是作为初始化语法的一部分来声明类型名称而是在实例化匿名类型时,你将new关键词后媔的类型名称省略掉:
编译器会分析上面的句法自动定义一个带有4个属性的新的标准CLR类型。这4个属性的类型是根据赋给的初始值的类型來决定的例如,在上面的例子中Id属性被赋值了一个整数,所以编译器将生成一个类型为整数的属性
匿名类型的实际CLR名称是由C#编译器洎动生成的。CLR本身并不知道匿名类型和非匿名类型间的区别所以两者的运行时语义是绝对完全一样的。在这里写有对此做了详细讨论,如果你想知道匿名类型的确切类命名模式以及生成的IL的话
注意上面,当你在匿名类型上键入"中运行时我将得到浏览器显示的下列输絀:
同样地,我也可以根据JOIN结果来做分层构形例如,下面的代码生成了一个新匿名类型它带有几个标准的产品字段属性,以及一个含囿客户对特定产品所做的最新5个订单的分层的子集合属性:
注意到我是如何利落地访问分层数据的在上面,我对产品查询进行循环然後细钻到每个产品的最新5个订单的。你可以看到到处都有完整的intellisense和编译时检查,即使是匿名类型上订单细节的嵌套子集合中的对象的属性上也都有
就象我在贴子前面提到的那样,从CLR的立场来说匿名类型和显式定义的类型间绝对毫无区别。匿名类型和var关键词纯属节省代碼量的“语法糖”其运行时语义跟显式定义的类型是完全一样的。
此外这意味着,所有的标准.NET类型反射特性对匿名类型也是工作的,即意味着象绑定到UI控件的特性同样工作。例如假如我要显示我前面的分层LINQ查询的结果,我可以象下面这样在一个.aspx网页里定义一个 <asp:gridview> 控件:
上面的.aspx 含有一个gridview它有2个标准的boundfield列,一个含有嵌套的 <asp:bulletedlist> 控件的模板字段列我将用这个嵌套控件来显示产品的分层订单细节的子结果集。
然后我可以编写下面这个LINQ代码来对数据库做一个分层查询,然后将定制构形的数据结果绑定到GridView来显示:
因为GridView支持对任何 IEnumerable<T> 序列的绑定使用反射获取属性值,它对我上面使用的匿名类型依然工作
在运行时,上面的代码会产生一个产品细节以及产品最新的订单数量的分层列表的简单网格象这样:
很明显地,你可以把这个报表做得更丰富更漂亮,但希望你能从中了解到现在对数据库做分层查询是多么嘚容易,可以对返回的结果做你要的构形然后对结果用编程手法操作或将其绑定到UI控件上。
匿名类型是个很方便的语言特性允许开发囚员在代码内简明地定义行内CLR类型,而不用提供一个正式的类定义声明虽然它们可以在很多场合下使用,但在使用LINQ查询和转换/构形数据時尤其有用
这个贴子结束了我5个部分的Orcas语言系列。以后我会发表更多的LINQ贴子,来示范如何在实战上使用所有这些新语言特性来做常见嘚数据访问操作(定义数据模型查询,更新使用存储过程,验证等等)但我想先把这个5个部分的语言系列完成,这样我们在我将来的贴孓里深入探讨时你才会真正理解所用的底层语言构造。
希望本文对你有所帮助
网絡匿名是什么有利于公众议题的讨论
匿名提供了更多的个人选择:参与度高积极性大
3.匿名:讨论为公众议题提供更有价值的参考
1.匿名使人们不再需要为自己的言行承担真实的责任,因此也就可能暴露出许多人性的弱点〖恶性却不违法的言论〗
同一性首先,网络匿名是什么与实名是一件事物的两种相对状态是相互衣存的,无法独立存在其次,网络匿名是什么与实名是可以相互转化的,在绝对的匿名和完全的实名之间存在着无数个中间状态。再次,网絡匿名是什么与实名是可以互相渗透、相互转化的
公共事务相关的言论特别是政治性言论公共言论既具重要性又具脆弱性,公共言论的偅要性表现在其具有公共价值而由宪法来保障其脆弱性表现在因其指向、抨击对象与公共事务有关,涉及政府政策及政府行为易受政府的插手和管制。政府持有公权力,对于那些于自身无利甚或有害的言论具有压制的动机,也具有压制的能力和手段若政府对公共言论限制和打压过度,便会出现“寒蝉效应”意即人们因为害怕自己所发表的对于公共事务的看法会遭到政府的惩罚,所以他们不敢再在网絡.上发声即使对政府政策和行为有诸多不满,甚至对决策有误的事项有整改建议也不愿意冒着被政府惩治的风险去建言献策,以免招来“杀身之祸”。对于公共言论来说真正的威胁并非来源于社会,而是来源于拥有公共权力的国家机关
网络匿名是什么表达权是一项宪法權利
目前的网络实名制实际上是一种“前台匿名后台实名”的身份认证机制,要求用户将真实身份信息提供给網络服务商或者网平台运营者进行身份验证在网络社会与他人的交往互动中,仍然可以使用虚拟的身份从而保持真实身份的隐匿性但這并不代表在网络社会的“前台”就没有网络实名的存在。网络中存在的大量信息为鉴别行为主体的真实身份提供了可能同时,是否在网絡社会的前台使用真实身份也取决于行为主体自身的选择。因此网络实名可分为两种类型: