通过反射和隐式强制转换创建泛型列表
本文关键字:转换 创建 泛型 列表 反射 | 更新日期: 2023-09-27 17:54:42
我的目标是.Net框架的4.0版本。我写了以下简单的代码:
public class A
{
public A()
{
}
}
public class B
{
public B()
{
}
public static implicit operator A(B b)
{
return new A();
}
}
然后我创建了一个通用列表:
var mylist = typeof(List<>).MakeGenericType(typeof(A)).GetConstructor(Type.EmptyTypes).Invoke(new object[]{});
当我想添加B
的新实例时,以下代码有效:
((IList<A>)mylist).Add(new B());
但是,如果我运行以下代码,则会引发以下异常:
The value "B" is not of type "A" and cannot be used in this generic collection.
参数名称:值
((IList)mylist).Add(new B());
当您将类型为B
的对象添加到IList<A>
时,隐式转换仅发生在第一个Add
中。在第二种情况下,您将其添加到非通用IList
,这是一个对象集合,当对象实际添加到List<A>
时,隐式转换不会发生并爆炸
即使这样也会失败:
var mylist = new List<A>();
((IList<A>)mylist).Add(new B());
((IList)mylist).Add(new B())
然而,你可以这样做:
((IList)mylist).Add((A)new B());
问题是,当您将列表强制转换为IList<A>
并调用Add
时,编译器(隐式(将B
实例的强制转换添加到A
。在第二种情况下,IList
只接受Add
方法中的object
。B
是一个对象,因此它不会强制转换为A
。因此,当该方法尝试在内部将其添加到底层数据结构时,会引发异常。
你甚至可以通过以下代码进行测试:
var fails = (A) (object) new B();
既然你问如何解决这个问题(尽管我认为在这种情况下没有必要将类型强制转换为IList
(,那么在添加它时,你可以直接将B
显式强制转换为A
。示例:
mylist.Add((A) new B());