匿名类型和动态类型列表...混淆不清

3
我发现在.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方法不行。

谢谢!


为什么你想在那种情况下使用动态类型?你正在创建一个通用的列表。你也没有说出你收到了什么错误或警告,这可能是相关的。 - Lazarus
2个回答

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" }));

啊!现在一切都清楚了。感谢您的帮助!再次感谢,我使用方法B,因为它是一个更干净的解决方案,这有助于澄清为什么方法A一开始没有起作用。 - Terry
果然,如果我创建一个函数:T Cast<T>(T sampleItem, object item) { return (T)item; } 然后调用 list.Add(Cast(newItem, Activator.CreateInstance(newItem.GetType(), new object[] { Guid.NewGuid(), "Test 2" })))); 它可以正常工作。再次感谢! - Terry

0
要让方法A起作用,你需要做的就是对你添加的Activator结果进行dynamic转换。很多人不知道C#动态调用默认使用静态类型来确定方法签名。因此,通过将参数也转换为dynamic,你告诉它使用运行时类型。
   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" }));

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接