【问题标题】:List of Anonymous Type and Dynamics... Confused匿名类型和动态列表...困惑
【发布时间】:2011-02-04 16:24:35
【问题描述】:

我在 .NET 中发现了一些与我预期的有点不同的东西。我粘贴的代码没有意义,但它是我拥有的更复杂函数的精简版本。我基本上将匿名类型信息作为参数获取(尚未创建匿名类型的实例),我需要创建该类型的列表,填充它,然后返回列表。现在,我找到了解决方案,但我想知道为什么方法 B 有效,而方法 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 无效。

谢谢!

【问题讨论】:

  • 为什么要在那种情况下使用动态?您正在创建一个通用列表。您也没有说您收到的错误或警报可能是相关的。

标签: dynamic c#-4.0 anonymous-types


【解决方案1】:

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

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

【讨论】:

  • 啊!现在一切都说得通了。谢谢您的帮助!我再次使用方法 B,因为它是一种更清洁的解决方案,这有助于弄清楚为什么方法 A 一开始就不起作用。
  • 果然,如果我创建一个函数:T Cast(T sampleItem, object item) { return (T)item; } 然后调用 list.Add(Cast(newItem, Activator.CreateInstance(newItem.GetType(), new object[] { Guid.NewGuid(), "Test 2" })));它工作得很好。再次感谢!
【解决方案2】:

要使方法 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" }));

}

【讨论】:

    猜你喜欢
    • 2014-05-08
    • 1970-01-01
    • 2010-09-28
    • 1970-01-01
    • 1970-01-01
    • 2019-06-25
    • 1970-01-01
    • 1970-01-01
    • 2012-01-17
    相关资源
    最近更新 更多