我想了解动态关键字在以下代码中的工作原理。我发现了一些帖子,讨论了如何在IList上调用Add()导致RuntimeBinderException,但是没有解释为什么以下代码不起作用:
[TestFixture]
public class TestDynamicOfIList
{
[Test]
public void Test1()
{
dynamic d1 = new ClassA();
dynamic d2 = new ClassA();
List<dynamic> dynamicList = new List<dynamic>();
dynamicList.Add(d1);
dynamicList.Add(d2);
ClassGroup group = new ClassGroup();
foreach (dynamic dynamicClassA in dynamicList)
{
// using var will fail during runtime! Need to use explicit type
var sameObject = DoNothing(dynamicClassA);
group.ClassAList.Add(sameObject);
}
}
private ClassA DoNothing(dynamic classA)
{
return classA;
}
public class ClassA
{
}
public class ClassGroup
{
public IList<ClassA> ClassAList { get; } = new List<ClassA>();
}
}
}
在上面的代码中,ClassGroup.ClassAList属性有一个已定义的类&Class;&#39; ClassA&#39;对于通用的IList&lt;&gt;,我不明白为什么编译器无法进行类型检查,也没有在运行时失败。
这里有几个我在StackOverflow上发现的类似问题:
How to create a List with a dynamic object type C#
Does not contain a definition for "Add"
为什么当我使用var sameObject
时,它无效,但使用ClassA sameObject
它可以正常工作?似乎认为sameObject
变量的类型当方法DoNothing()
明确返回ClassA
答案 0 :(得分:2)
This question回答了编译器确定sameObject
为dynamic
的原因。
一个更简单的例子来证明这一点:
dynamic d1 = new ClassA();
var s = DoNothing(d1);
IList<ClassA> c = new List<ClassA>();
c.Add(s);
Add
IList
不起作用的原因似乎归结为重载解决方案。运行时无法在Add
上找到要使用的IList
重载,因此会抛出异常。您已经知道,如果您明确说明它的工作类型,那么这是解决问题的可能方法。
有趣的是,如果您使用ICollection<ClassA>
(建议here),它确实有效,因此IList
界面似乎存在问题:
dynamic d1 = new ClassA();
var s = DoNothing(d1);
ICollection<ClassA> c = new List<ClassA>();
c.Add(s);
答案 1 :(得分:-1)
我真的想知道为什么使用“var sameObject”不起作用
您正试图在Add
上致电IList
,这就是为什么它无效。您可以通过两种方式解决问题:
修复1
调用ToList()
然后添加对象。
group.ClassAList.ToList().Add(sameObject);
修复2
从您的财产返回List
:
public class ClassGroup
{
public List<ClassA> ClassAList { get; } = new List<ClassA>();
}