我在.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.
谢谢!
答案 0 :(得分:2)
因为在方法B中,您使用显式IList.Add(object)
,它接受一个对象并尝试将其强制转换为匿名类型。在方法A中,您有List<anonymous type>
,并且您正在使用通用的Add方法并尝试添加对象,但是您得到RuntimeBinderException
,因为它期望正确的类型。如果您没有使用dynamic
,则会看到编译器错误。要使用显式IList.Add
,请使用
((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" }));
}