匿名types – 是否有任何distingushing特性?
有没有什么可以用来确定一个types是否实际上是一个匿名types? 例如一个接口等?
目标是创build如下的东西…
//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");
还是仅仅是一个匿名types的美丽? 没有什么可以识别自己,因为它需要一个新的形状?
注意 – 我意识到你可以为对象类写一个扩展方法,但在我看来,这似乎有点矫枉过正。
编辑:下面的列表适用于C#匿名types。 VB.NET有不同的规则 – 特别是,它可以生成可变的匿名types(默认情况下)。 Jared在评论中指出,命名风格也是不同的。 基本上这是非常脆弱的…
您不能在通用约束中识别它,但是:
- 它将是一个类(而不是接口,枚举,结构等)
- 它将应用CompilerGeneratedAttribute
- 它将覆盖Equals,GetHashCode和ToString
- 它将位于全局命名空间中
- 它不会嵌套在另一种types中
- 这将是内部的
- 它将被密封
- 它将直接从
object
派生 - 它将与属性一样具有许多types参数。 (你可以有一个非generics的匿名types,没有属性,但是有点没有意义。)
- 每个属性都有一个types参数,其名称包括属性名称,并且将是该types的参数,例如,Name属性成为types<> _ Name的属性
- 每个属性将是公共和只读
- 对于每个财产将有一个相应的只读私人领域
- 将不会有其他的财产或领域
- 将会有一个构造函数,每个types参数对应一个参数,顺序与types参数相同
- 每个方法和属性都将应用DebuggerHiddenAttribute 。
- 该types的名称将以“<>”开头,并包含“AnonymousType”
但是,很less有这样的规格保证 – 所以它可以在下一版本的编译器中改变,或者如果你使用Mono等。
我记得,有一个[CompilerGenerated]
标记… 2秒
加上这个名字会很怪,而且会是一个genericstypes; -p
其实,对于“得到”等我可能只是使用静态(非扩展)的方法。
如果你只是想从一个anon-type的实例(在以后的时间点)获取值,lambda可能是最好的select – 注意你需要一些技巧来解决这个问题:
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
为了扩展方法的目的,无法区分匿名types。 扩展方法通过指定编译时可命名types的方法来工作。 匿名types是不可命名的,因此在编译时不可见。 这使得它们与扩展方法不兼容。