This article is currently in the process of being translated into Chinese (~91% done).
Anonymous Types
目前为止,大家应该都知道对象基本来自类定义。类定义了一系列的字段,属性和/或方法,然后就可以实例化类生成对象了。不过,通过引入匿名类型,就不再需要先定义类再生成对象了。不用担心,类概念不会消亡,因为匿名类型(或对象)还是有不少限制,只是对某些特殊场景比较有用!
匿名类型的初始化使用new操作符,加上对象初始化器 - 这看起来很象是类的实例化,只是不需要类名称。此外,由于匿名对象背后没有类,在定义指向匿名对象的变量时必需用var关键字。听起来好复杂,但下例将展示这一点都不复杂:
var user = new
{
Name = "John Doe",
Age = 42
};
Console.WriteLine(user.Name + " - " + user.Age + " years old");就这样 - 一个包含用户信息(姓名和年龄)的对象诞生了。匿名类型在很多情况下很有用,尤其当只需要快速返回某些比单个字符串或数字更复杂一些的东西时。匿名类型可以凭空生成属性,不用操心类定义,还要在需要时修改类定义。不过前面已提到,在考虑使用匿名类型替代类定义时要注意几点限制:
- 不象真实的类,匿名类型不能有字段或方法 - 只能有属性。
- 一旦匿名对象被初始化,就不能再增加新的属性了。
- 所有属性都是只读的 - 匿名对象一经初始化,就不能改变其属性值了。
虽然有这些限制,匿名类型对很多任务还是很实用的。常见用法是用于简化一个复杂对象(来自一个已定义的类),如,由于必需把对象维持在尽可能小的尺寸以便发送到浏览器上,或是因为完整对象内包含敏感信息不能被暴露给用户。匿名类型很适合处理此类问题,如下例所示:
using System;
using System.IO;
namespace AnonymousTypes
{
class Program
{
static void Main(string[] args)
{
string pathOfExe = System.Reflection.Assembly.GetEntryAssembly().Location;
FileInfo fileInfo = new FileInfo(pathOfExe);
var simpleFileInfo = new
{
Filename = fileInfo.Name,
FileSize = fileInfo.Length
};
Console.WriteLine("File name: " + simpleFileInfo.Filename + ". Size: " + simpleFileInfo.FileSize + " bytes");
}
}
}第一行代码获取当前执行文件,即本程序本身的文件名称。使用此文件名生成的FileInfo类实例包含了非常多此文件的信息。但有时不需要这么多信息,因此可以使用来自原始FileInfo类实例的信息,以匿名类型建立一个简单的版本。最后一行代码使用此信息做了一些简单的输出操作。
注意上例为匿名类型的每个属性都进行了命名(Filename和FileSize) - 由于后续需要访问它们,这似乎很有必要。不过,对于基于现存的对象的信息生成的匿名对象,也可以不对其属性命名,而让编译器直接使用其被赋值的信息名称,象这样:
var simpleFileInfo = new
{
fileInfo.Name,
fileInfo.Length
};此时属性就变成了Name和Length而非Filename和FileSize。如果完全不关心属性名称,或者本就想使用原始对象的属性名称,这样做就很方便。
总结
匿名类型可以快速实例化带有一个或多个属性的对象。这些属性是只读的,且在实例化后不能再增加新的属性。