我注意到使用接口列表作为构造函数参数的泛型类的奇怪行为。
我们说我们有以下课程
public class GenericClass<T> where T : IInterface
{
public GenericClass(int inInt, List<T> inList){
}
public GenericClass(int inInt, object inObject){
}
}
当我尝试创建这样的实例时(tmpType实现IInterface
):
IEnumerable<IInterface> tmpSomeObjects = xy;
Activator.CreateInstance(typeof(GenericClass<>).MakeGenericType(tmpType), 5, (List<IInterface>)tmpSomeObjects);
将调用第二个构造函数(int,object)。
我可能会错过一个重点...我期望第一个构造函数被执行。
答案 0 :(得分:4)
您的IEnumerable
类型为IEnumerable<IInterface>
,但您构建的类型具有派生类型的泛型参数,因此它与确切的构造函数不匹配。
说T
为Foo
(实现IInterface
),您的类型变为:
public class GenericClass<Foo>
{
public GenericClass(int inInt, List<Foo> inList){
}
public GenericClass(int inInt, object inObject){
}
}
然而,你传递的是IEnumerable<IInterface>
(或List<IInterface>
),与List<Foo>
不匹配,所以这就是为什么它更喜欢object
(不仅仅是首选) ......其他构造函数根本不匹配。
尝试:使用object
删除构造函数并尝试执行此操作:
var list = new List<IInterface>();
var x = new GenericClass<TypeImplementingIInterface>(5, list);
甚至不会编译。
因此,您的案例中的解决方案很简单...在构造函数IEnumerable<IInterface>
中创建参数,而不是List<T>
,这是您实际想要传递的参数
答案 1 :(得分:3)
您正在尝试这样做:
var list = new List<IInterface>();
new GenericClass<TmpType>(5, list);
但是,List<IInterface>
无法转换为List<TmpType>
,即使TmpType
实现IInterface
,也会选择对象重载。
如果您尝试使用:
var list = new List<TmpType>();
// should work with Activator.CreateInstance too
new GenericClass<TmpType>(5, list);
然后它应该选择第一个。
请注意Activator.CreateInstance
,与&#34;手册&#34;不同。调用,list
的运行时类型很重要。例如,这个:
IEnumerable<IInterface> list = new List<TmpType>();
Activator.CreateInstance(typeof(GenericType<>)).MakeGenericType(typeof(TmpType)), 5, list);
将选择第一个重载,因为运行时类型为List<TmpType>
。但是这个:
IEnumerable<IInterface> list = new List<TmpType>();
new GenericClass<TmpType>(1, list);
将选择第二个(带object
),因为现在构造函数在编译时被解析。