次のメソッドがあるとしましょう。
public object Test()
{
return new { A = "Test" };
}
Aに格納されている値を取得する可能性はありますか?
var b = Test(); //Any chance to cast this to the anonymous type?
次のメソッドがあるとしましょう。
public object Test()
{
return new { A = "Test" };
}
Aに格納されている値を取得する可能性はありますか?
var b = Test(); //Any chance to cast this to the anonymous type?
匿名型またはメソッドから返すTuple<>
ことは悪いことであることに注意してください
しかし、あなたは「それは良い考えですか」ではなく、それを行う方法について質問しました...
動的または反射を使用して...
dynamic b = Test();
string str = b.A;
または不正行為によって:
public static object Test()
{
return new { A = "Test" };
}
public static string GetA(object obj)
{
// We create an anonymous type of the same type of the one in Test()
// just to have its type.
var x = new { A = string.Empty };
// We pass it to Cast, that will take its T from the type of x
// and that will return obj casted to the type of the anonymous
// type
x = Cast(x, obj);
// Now in x we have obj, but strongly typed. So x.A is the value we
// want
return x.A;
}
public static T Cast<T>(T type, object obj) where T : class
{
return (T)obj;
}
string str = GetA(Test());
C# では、同じアセンブリにある同じ型の同じプロパティを持つすべての匿名型がマージされます。したがって、new { A }
ofTest()
と ofGetA()
は同じ型です。
これCast<T>
は、匿名型から型を抽出するための便利なトリックです。最初のパラメーターとして型指定された匿名型を渡し (パラメーターはジェネリックを「アクティブ化」するためだけに使用されますT
)、2 番目のパラメーターとしてキャストするオブジェクトを渡します。同様のトリックを使用して、ジェネリック型のコレクションを作成できます。
public static T MakeList<T>(T type)
{
return new List<T>();
}
//これを匿名型にキャストする機会はありますか?
はい、例によってキャストを使用できます。
public static T CastByExample<T>(this object obj, T example) {
return (T)obj;
}
これは、同じアセンブリにいる場合にのみ機能することに注意してください。匿名型は、同じアセンブリである場合は同じ型を持ち、プロパティは同じ型の同じ名前を同じ順序で持ちます。
それで:
object b = Test();
var example = new { A = "example" };
var casted = b.CastByExample(example);
Console.WriteLine(casted.A);
または、次を使用できますdynamic
。
dynamic b = Test();
Console.WriteLine(b.A);
または、リフレクションを使用します。
object b = Test();
var property = b.GetType().GetProperty("A");
var value = property.GetValue(b);
Console.WriteLine(value);
または、正しいことをして、名目上の (つまり、非匿名の) type を作成することもできます。
これを匿名型にキャストする機会はありますか?
あなたはそれを行うことができますが、それは非常に信頼性が低いです. 匿名型の作成を変更するたびに、コードが突然他の場所で跡形もなく壊れてしまうからです。
ここの Jon Skeet によるブログで、匿名型のキャストのすべての失敗を読むことができます。Marc Gravel のコメントも読む価値があります。
上記のブログで説明されている重大な変更の例。
using System;
static class GrottyHacks
{
internal static T Cast<T>(object target, T example)
{
return (T) target;
}
}
class CheesecakeFactory
{
static object CreateCheesecake()
{
return new { Fruit="Strawberry", Topping="Chocolate" };
}
static void Main()
{
object weaklyTyped = CreateCheesecake();
var stronglyTyped = GrottyHacks.Cast(weaklyTyped,
new { Fruit="", Topping="" });
Console.WriteLine("Cheesecake: {0} ({1})",
stronglyTyped.Fruit, stronglyTyped.Topping);
}
}
すべて良い。CreateCheseCake を次のように変更する必要があることに突然気づいたらどうしますか。
static object CreateCheesecake()
{
return new { Fruit="Strawberry", Topping="Chocolate", Base = "Biscuit" };
}
次に、この行はどうなりますか
var stronglyTyped = GrottyHacks.Cast(weaklyTyped,
new { Fruit="", Topping="" });
もううまくいきません。