匿名类型(C# 编程指南)Anonymous Types (C# Programming Guide)

匿名类型提供了一种方便的方法,可用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型。Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly define a type first. 类型名由编译器生成,并且不能在源代码级使用。The type name is generated by the compiler and is not available at the source code level. 每个属性的类型由编译器推断。The type of each property is inferred by the compiler.

可通过使用 new 运算符和对象初始值创建匿名类型。You create anonymous types by using the new operator together with an object initializer. 有关对象初始值设定项的详细信息,请参阅对象和集合初始值设定项For more information about object initializers, see Object and Collection Initializers.

以下示例显示了用两个名为 AmountMessage 的属性进行初始化的匿名类型。The following example shows an anonymous type that is initialized with two properties named Amount and Message.

var v = new { Amount = 108, Message = "Hello" };  

// Rest the mouse pointer over v.Amount and v.Message in the following  
// statement to verify that their inferred types are int and string.  
Console.WriteLine(v.Amount + v.Message);  

匿名类型通常用在查询表达式的 select 子句中,以便返回源序列中每个对象的属性子集。Anonymous types typically are used in the select clause of a query expression to return a subset of the properties from each object in the source sequence. 有关查询的详细信息,请参阅 LINQ 查询表达式For more information about queries, see LINQ Query Expressions.

匿名类型包含一个或多个公共只读属性。Anonymous types contain one or more public read-only properties. 包含其他种类的类成员(如方法或事件)为无效。No other kinds of class members, such as methods or events, are valid. 用来初始化属性的表达式不能为 null、匿名函数或指针类型。The expression that is used to initialize a property cannot be null, an anonymous function, or a pointer type.

最常见的方案是用其他类型的属性初始化匿名类型。The most common scenario is to initialize an anonymous type with properties from another type. 在下面的示例中,假定名为 Product 的类存在。In the following example, assume that a class exists that is named Product. Product 包括 ColorPrice 属性,以及你不感兴趣的其他属性。Class Product includes Color and Price properties, together with other properties that you are not interested in. 变量 Product``products 是 对象的集合。Variable products is a collection of Product objects. 匿名类型声明以 new 关键字开始。The anonymous type declaration starts with the new keyword. 声明初始化了一个只使用 Product 的两个属性的新类型。The declaration initializes a new type that uses only two properties from Product. 这将导致在查询中返回较少数量的数据。This causes a smaller amount of data to be returned in the query.

如果你没有在匿名类型中指定成员名称,编译器会为匿名类型成员指定与用于初始化这些成员的属性相同的名称。If you do not specify member names in the anonymous type, the compiler gives the anonymous type members the same name as the property being used to initialize them. 必须为使用表达式初始化的属性提供名称,如下面的示例所示。You must provide a name for a property that is being initialized with an expression, as shown in the previous example. 在下面示例中,匿名类型的属性名称都为 Price``Color 和 。In the following example, the names of the properties of the anonymous type are Color and Price.

var productQuery = 
    from prod in products
    select new { prod.Color, prod.Price };

foreach (var v in productQuery)
{
    Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}

通常,当使用匿名类型来初始化变量时,可以通过使用 var 将变量作为隐式键入的本地变量来进行声明。Typically, when you use an anonymous type to initialize a variable, you declare the variable as an implicitly typed local variable by using var. 类型名称无法在变量声明中给出,因为只有编译器能访问匿名类型的基础名称。The type name cannot be specified in the variable declaration because only the compiler has access to the underlying name of the anonymous type. 有关 var 的详细信息,请参阅隐式类型本地变量For more information about var, see Implicitly Typed Local Variables.

可通过将隐式键入的本地变量与隐式键入的数组相结合创建匿名键入的元素的数组,如下面的示例所示。You can create an array of anonymously typed elements by combining an implicitly typed local variable and an implicitly typed array, as shown in the following example.

var anonArray = new[] { new { name = "apple", diam = 4 }, new { name = "grape", diam = 1 }};  

备注Remarks

匿名类型是直接从对象派生的类型,并且其无法强制转换为除对象外的任意类型。Anonymous types are class types that derive directly from object, and that cannot be cast to any type except object. 虽然你的应用程序不能访问它,编译器还是提供了每一个匿名类型的名称。The compiler provides a name for each anonymous type, although your application cannot access it. 从公共语言运行时的角度来看,匿名类型与任何其他引用类型没有什么不同。From the perspective of the common language runtime, an anonymous type is no different from any other reference type.

如果程序集中的两个或多个匿名对象初始值指定了属性序列,这些属性采用相同顺序且具有相同的名称和类型,则编译器将对象视为相同类型的实例。If two or more anonymous object initializers in an assembly specify a sequence of properties that are in the same order and that have the same names and types, the compiler treats the objects as instances of the same type. 它们共享同一编译器生成的类型信息。They share the same compiler-generated type information.

无法将字段、属性、时间或方法的返回类型声明为具有匿名类型。You cannot declare a field, a property, an event, or the return type of a method as having an anonymous type. 同样,你不能将方法、属性、构造函数或索引器的形参声明为具有匿名类型。Similarly, you cannot declare a formal parameter of a method, property, constructor, or indexer as having an anonymous type. 要将匿名类型或包含匿名类型的集合作为参数传递给某一方法,可将参数作为类型对象进行声明。To pass an anonymous type, or a collection that contains anonymous types, as an argument to a method, you can declare the parameter as type object. 但是,这样做会使强类型化作用无效。However, doing this defeats the purpose of strong typing. 如果必须存储查询结果或者必须将查询结果传递到方法边界外部,请考虑使用普通的命名结构或类而不是匿名类型。If you must store query results or pass them outside the method boundary, consider using an ordinary named struct or class instead of an anonymous type.

由于匿名类型上的 GetHashCodeEqualsGetHashCode``Equals 方法是根据方法属性的 和 定义的,因此仅当同一匿名类型的两个实例的所有属性都相等时,这两个实例才相等。Because the Equals and GetHashCode methods on anonymous types are defined in terms of the Equals and GetHashCode methods of the properties, two instances of the same anonymous type are equal only if all their properties are equal.

请参阅See Also

C# 编程指南C# Programming Guide
对象和集合初始值设定项Object and Collection Initializers
C# 中的 LINQ 入门Getting Started with LINQ in C#
LINQ 查询表达式LINQ Query Expressions