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

EDIT: The list below applies to C# anonymous types. VB.NET has different rules - in particular, it can generate mutable anonymous types (and does by default). Jared has pointed out in the comment that the naming style is different, too. Basically this is all pretty fragile...

You can't identify it in a generic constraint, but:

  • It will be a class (rather than interface, enum, struct etc)
  • It will have the CompilerGeneratedAttribute applied to it
  • It will override Equals, GetHashCode and ToString
  • It will be in the global namespace
  • It will not be nested in another type
  • It will be internal
  • It will be sealed
  • It will derive directly from object
  • It will be generic with as many type parameters as properties. (You can have a non-generic anonymous type, with no properties. It's a bit pointless though.)
  • Each property will have a type parameter with a name including the property name, and will be of that type parameter, e.g. the Name property becomes a property of type <>_Name
  • Each property will be public and read-only
  • For each property there will be a corresponding readonly private field
  • There will be no other properties or fields
  • There will be a constructor taking one parameter corresponding to each type parameter, in the same order as the type parameters
  • Each method and property will have the DebuggerHiddenAttribute applied to it.
  • The name of the type will start with "<>" and contain "AnonymousType"

Very little of this is guaranteed by the specification, however - so it could all change in the next version of the compiler, or if you use Mono etc.

于 2008-11-24T19:38:13.950 に答える
4

そういえば[CompilerGenerated]マーカーが… 2秒

さらに、名前はおかしくなり、ジェネリック型になります;-p

実際、「get」などの場合、おそらく静的(非拡張)メソッドを使用するだけです。

(後で) anon-type のインスタンスから値を取得する方法が必要な場合は、おそらくラムダが最適なオプションです。これを実現するには、いくつかのトリックが必要であることに注意してください。

    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 に答える