C#3.0新特性(三)

匿名类型

  匿名类型提供了一种方便的方法,可用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型。类型名由编译器生成,并且不能在源代码级使用。这些属性的类型由编译器推断。下面的示例演示一个用两个分别名为 Amount 和 Message 的属性初始化的匿名类型。

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

匿名类型通常用在查询表达式的 select 子句中,以便返回源序列中每个对象的属性子集。

匿名类型是使用 new 运算符和对象初始值设定项创建的。有关对象初始值设定项的更多信息,请参见对象和集合初始值设定项(C# 编程指南)。

匿名类型是由一个或多个公共只读属性组成的类类型。不允许包含其他种类的类成员(如方法或事件)。

最常见的方案是用其他类型的一些属性初始化匿名类型。在下面的示例中,假定一个名为 Product 的类包含 Color 和 Price 属性以及其他几个您不感兴趣的属性。Products 是一个 Product 对象集合。匿名类型声明以 new 关键字开始。它初始化了一个只使用 Product 的两个属性的新类型。这将导致在查询中返回较少数量的数据。

如果您没有在匿名类型中指定成员名称,编译器会为匿名类型成员指定与用于初始化这些成员的属性相同的名称。必须为使用表达式初始化的属性提供名称。

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 构造初始化该变量。这是因为只有编译器能够访问匿名类型的基础名称。有关 var 的更多信息,请参见隐式类型的局部变量(C# 编程指南)。

备注
匿名类型是直接从对象派生的引用类型。尽管应用程序无法访问匿名类型,但编译器仍会为其提供一个名称。从公共语言运行库的角度来看,匿名类型与任何其他引用类型没有什么不同。

如果两个或更多个匿名类型以相同的顺序具有相同数量和种类的属性,则编译器会将这些匿名类型视为相同的类型,并且它们共享编译器生成的相同类型信息。

匿名类型具有方法范围。若要向方法边界外部传递一个匿名类型或一个包含匿名类型的集合,必须首先将匿名类型强制转换为对象。但是,这会使匿名类型的强类型化无效。如果必须存储查询结果或者必须将查询结果传递到方法边界外部,请考虑使用普通的命名结构或类而不是匿名类型。

匿名类型不能像属性一样包含不安全类型。

由于匿名类型上的 Equals 和 GetHashCode 方法是根据属性的 Equals 和 GetHashcode 定义的,因此仅当同一匿名类型的两个实例的所有属性都相等时,这两个实例才相等。

PS:匿名类型只会为不同的参数列表的结构:参数的名称,参数的数据类型,参数的相互顺序定义不同的Type。而具有相同的参数列表的{M1=?, M2 =? , …}会共享同一个Type。但是这种机制仅限于在同一个Assembly中

原文地址:https://www.cnblogs.com/jeriffe/p/1808180.html