匿名类型和动态列表...困惑

时间:2011-02-04 16:24:36

标签: dynamic c#-4.0 anonymous-types

我在.NET中发现了一些与我预期的不同的东西。我粘贴的代码没有意义,但它是我所拥有的更复杂功能的浓缩版本。我实际上是将匿名类型信息作为参数(没有创建匿名类型的实例),我需要创建该类型的列表,填充它,然后返回列表。现在,我找到了一个解决方案,但我想知道方法B的工作原理,但不是方法A.

方法A:

static void Main(string[] args)
{
    var newItem = new {  ID = Guid.NewGuid(), Name = "Test" };
    dynamic list;

    list = Activator.CreateInstance(typeof(List<>).MakeGenericType(newItem.GetType()));

    list.Add(newItem);
    list.Add(Activator.CreateInstance(newItem.GetType(), new object[] { Guid.NewGuid(), "Test 2" }));
}

方法B:

static void Main(string[] args)
{
    var newItem = new {  ID = Guid.NewGuid(), Name = "Test" };
    System.Collections.IList list;

    list = (System.Collections.IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(newItem.GetType()));

    list.Add(newItem);
    list.Add(Activator.CreateInstance(newItem.GetType(), new object[] { Guid.NewGuid(), "Test 2" }));
}

同样,我不是在寻找解决方案,只是好奇为什么方法B可以工作而不是方法A.

谢谢!

2 个答案:

答案 0 :(得分:2)

因为在方法B中,您使用显式IList.Add(object),它接受​​一个对象并尝试将其强制转换为匿名类型。在方法A中,您有List<anonymous type>,并且您正在使用通用的Add方法并尝试添加对象,但是您得到RuntimeBinderException,因为它期望正确的类型。如果您没有使用dynamic,则会看到编译器错误。要使用显式IList.Add,请使用

更改方法A.
((IList)list).Add(
    Activator.CreateInstance(newItem.GetType(), 
        new object[] { Guid.NewGuid(), "Test 2" }));

答案 1 :(得分:0)

要使方法A正常工作,您需要做的就是dynamic转换您要添加的Activator结果。许多人没有意识到C#动态调用实际上默认使用静态类型来确定方法签名。因此,通过将参数转换为动态,您告诉它使用运行时类型。

   static void Main(string[] args)
{
    var newItem = new {  ID = Guid.NewGuid(), Name = "Test" };
    dynamic list;

    list = Activator.CreateInstance(typeof(List<>).MakeGenericType(newItem.GetType()));

    list.Add(newItem);
    list.Add((dynamic)Activator.CreateInstance(newItem.GetType(), new object[] { Guid.NewGuid(), "Test 2" }));

}