28

有什么东西可以用来确定一个类型是否真的是匿名类型?例如接口等?

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

//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");

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

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

4

3 回答 3

60

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

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

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

然而,规范很少保证这一点 - 因此它可能会在下一版本的编译器中发生变化,或者如果您使用 Mono 等。

于 2008-11-24T19:38:13.950 回答
4

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

再加上名字会很奇怪,它会是一个通用类型;-p

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

如果您只是想要一种从匿名类型的实例中获取值的方法(在以后的某个时间点),那么 lambda 可能是最好的选择 - 请注意,您需要一些技巧来实现这一点:

    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
于 2008-11-24T19:23:52.093 回答
0

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

于 2008-11-24T19:24:24.650 回答