匿名类型 - 有任何区别特征吗?

时间:2008-11-24 19:21:48

标签: c# .net generics extension-methods anonymous-types

有什么可以用来确定某个类型是否真的是匿名类型?例如一个界面等?

目标是创建类似以下的内容......

//defined like...
public static T Get<T>(this IAnonymous obj, string prop) {
    return (T)obj.GetType().GetProperty(prop).GetValue(obj, null);
}
//...

//And then used like...
var something = new { name = "John", age = 25 };
int age = something.Get<int>("age");

或者这只是匿名类型的美丽?没有什么可以自我识别,因为它需要一个新的形状?

注意 - 我意识到您可以为对象类编写扩展方法,但在我看来,这看起来有点矫枉过正。

3 个答案:

答案 0 :(得分:55)

编辑:以下列表适用于C#匿名类型。 VB.NET有不同的规则 - 特别是,它可以生成可变的匿名类型(默认情况下)。 Jared在评论中指出,命名风格也不同。基本上这都非常脆弱......

您无法在通用约束中识别它,但是:

  • 它将是一个类(而不是接口,枚举,结构等)
  • 它将CompilerGeneratedAttribute应用于它
  • 它将覆盖Equals,GetHashCode和ToString
  • 它将位于全局命名空间
  • 它不会嵌套在另一种类型
  • 这将是内部的
  • 将被密封
  • 它将直接来自object
  • 与属性一样多的类型参数是通用的。 (你可以有一个非通用的匿名类型,没有属性。虽然它有点无意义。)
  • 每个属性都有一个类型参数,其名称包含属性名称,并且属于该类型参数,例如Name属性成为&lt;&gt; _Name
  • 类型的属性
  • 每个属性都是公开的,只读
  • 对于每个属性,都会有一个相应的只读私有字段
  • 没有其他属性或字段
  • 将有一个构造函数采用与每个类型参数对应的一个参数,其顺序与类型参数相同
  • 每个方法和属性都会应用DebuggerHiddenAttribute
  • 该类型的名称将以“&lt;&gt;”开头并包含“AnonymousType”

但是规范保证这一点很少 - 所以它可以在下一版本的编译器中更改,或者如果你使用Mono等。

答案 1 :(得分:4)

我记得,有一个[CompilerGenerated]标记...... 2秒

此外,该名称将是怪异的,并且它将是通用类型;-p

实际上,对于“获取”等,我可能只使用静态(非扩展)方法。

如果你只是想从anon-type的一个实例中获取值(在稍后的某个时间点),lambda可能是最好的选择 - 注意你需要一些技巧来解决这个问题:< / p>

    static void Main()
    {
        var foo = new { name = "John", age = 25 };
        var func = Get(foo, x => x.age);
        var bar = new { name = "Marc", age = 30 };
        int age = func(bar);
    }
    // template here is just for type inference...
    static Func<TSource, TValue> Get<TSource, TValue>(
        TSource template, Func<TSource, TValue> lambda)
    {
        return lambda;
    }

(编辑评论)肯定这个属性:

        var foo = new { A = "B" };
        Type type = foo.GetType();

        CompilerGeneratedAttribute attrib = (CompilerGeneratedAttribute) Attribute.GetCustomAttribute(
            type, typeof(CompilerGeneratedAttribute)); // non-null, therefore is compiler-generated

答案 2 :(得分:0)

出于扩展方法的目的,无法区分匿名类型。扩展方法通过为编译时可命名类型指定方法来工作。匿名类型是不可命名的,因此在编译时不可见。这使它们与扩展方法不兼容。