Activator创建通用实例

时间:2018-04-26 11:13:16

标签: c# generics

我注意到使用接口列表作为构造函数参数的泛型类的奇怪行为。

我们说我们有以下课程

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)。

我可能会错过一个重点...我期望第一个构造函数被执行。

2 个答案:

答案 0 :(得分:4)

您的IEnumerable类型为IEnumerable<IInterface>,但您构建的类型具有派生类型的泛型参数,因此它与确切的构造函数不匹配。

TFoo(实现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),因为现在构造函数在编译时被解析。