最早见识匿名类型是在 Java 语言中,这种纯技巧性的编码方式为局部数据交换带来很大的便利。
var user = new { Name = "Tom", Age = 13 };
Console.WriteLine(user.Name);
C# 3.0 对 new 关键字做了重新定义,增加对匿名类型的支持。
匿名类型特征:
(1) 编码时没有定义类型名称。
(2) 通过对象初始化器定义属性。
(3) 引用变量只能是隐式类型或 Object。
那么在这背后,编译器究竟干了些什么?(我快得编译器综合症了~~~)
反编译代码
var <>g__initLocal0 = new <>f__AnonymousType0 ();
<>g__initLocal0.Name = "Tom";
<>g__initLocal0.Age = 13;
var user = <>g__initLocal0;
Console.WriteLine(user.Name);
所谓匿名类型,依然是编译器这家伙在玩花样,它自动生成了一个名为 <>f__AnonymousType0 的泛型类型。
[CompilerGenerated, DebuggerDisplay(@"/{ Name = {Name}, Age = {Age} }", Type=" ")]
internal sealed class <>f__AnonymousType0
{
// Fields
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private T field3;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private U field4;
// Methods
public <>f__AnonymousType0();
[DebuggerHidden]
public override bool Equals(object value);
[DebuggerHidden]
public override int GetHashCode();
[DebuggerHidden]
public override string ToString();
// Properties
public U Age { get; set; }
public T Name { get; set; }
}
将匿名类型和隐式类型变量搭配,就可以继续使用 VS 的智能感知功能,不能不说 VS 真的很棒。
由于无法在编码时获得匿名类型的实际类型元数据,所以要在作用范围以外使用它就变得相当麻烦。
应用环境:
(1) 局部信息存储交换。
(2) LINQ 返回信息存储。
(3) 用于数据控件绑定源。
当然,我们可以使用反射来操作匿名类型。
static object GetAnonymousObject()
{
return new { Name = "Tom" };
}
static void Main(string[] args)
{
var a = GetAnonymousObject();
PropertyInfo p = a.GetType().GetProperty("Name");
Console.WriteLine(p.GetValue(a, null));
}
匿名类型在 LINQ 中的应用演示
int[] i = { 1, 2, 3, 4 };
var q = from x in i where x % 2 == 0 select new { Name = "user" + x, Age = x };
foreach (var o in q)
Console.WriteLine("{0}:{1}", o.Name, o.Age);
---------小小分隔线--------------------------
除了用 new 定义匿名类型外,我们还可以定义隐式类型数组(Implicitly typed arrays)。
var i = new[] { 1, 2, 3, 4 };
var s = new[] { "a", "b", "c" };
var c = new[] { 'a', 'b', 'c' };
var o = new[] { new object(), new object() };
var a = new[] { new { Name = "a" }, new { Name = "Jack" } };
Console.WriteLine(i.GetType());
Console.WriteLine(s.GetType());
Console.WriteLine(c.GetType());
Console.WriteLine(o.GetType());
Console.WriteLine(a.GetType());
输出:
System.Int32[]
System.String[]
System.Char[]
System.Object[]
<>f__AnonymousType0`1[System.String][]
定义隐式类型数组时,元素类型必须相同。如下编码会导致无法编译。
var a = new[] { new { Name = "a" }, new { Age = 13 } };
var x = new[] { 1, "a" };
错误信息
No best type found for implicitly typed array
from <http://www.rainsts.net/article.asp?id=505>