[Orcas] 7. Anonymous types

[ 2007-06-12 11:13:16 | 作者: yuhen ]
字号: | |
最早见识匿名类型是在 Java 语言中,这种纯技巧性的编码方式为局部数据交换带来很大的便利。
var user = new { Name = "Tom", Age = 13 };
Console.WriteLine(user.Name);

C# 3.0 对 new 关键字做了重新定义,增加对匿名类型的支持。

匿名类型特征:

(1) 编码时没有定义类型名称。
(2) 通过对象初始化器定义属性。
(3) 引用变量只能是隐式类型或 Object。

那么在这背后,编译器究竟干了些什么?(我快得编译器综合症了~~~[sad])

反编译代码
var <>g__initLocal0 = new <>f__AnonymousType0<string, int>();
<>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="<Anonymous Type>")]
internal sealed class <>f__AnonymousType0<T, U>
{
    // 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; }
}

[yes] 将匿名类型和隐式类型变量搭配,就可以继续使用 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
[最后修改由 yuhen, 于 2007-06-12 13:08:33]
评论Feed 评论Feed: http://www.rainsts.net/feed.asp?q=comment&id=505

这篇日志没有评论。

发表评论
表情图标
[smile] [confused] [cool] [cry]
[eek] [angry] [wink] [sweat]
[lol] [stun] [razz] [redface]
[rolleyes] [sad] [yes] [no]
[heart] [star] [music] [idea]
UBB代码
转换链接
表情图标
悄悄话
用户名:   密码:  
验证码 * 请输入验证码