为什么我无法创建列表<>使用myObject?

时间:2013-07-23 06:05:56

标签: c#

我动态创建了一个类(找到它here),但我不明白为什么我不能用它来创建列表?

var myType = CompileResultType();
var myObject = Activator.CreateInstance(myType);
var myList = new List<myObject>();

// Error: The type or namespace name 'myObject' 
// could not be found (are you missing a using directive 
// or an assembly reference?)

我该怎么做?

6 个答案:

答案 0 :(得分:8)

它们被称为泛型类型参数,因为它们需要类型,而不是实例。因此,您需要知道实际类型或使用反射创建列表对象。

Type listType = typeof(List<>);
Type dynamicClassType = listType.MakeGenericType(myObject.GetType());
object myList = Activator.CreateInstance(dynamicClassType);

但是,您无法以任何有意义的方式使用实例,因为它是一个对象。

  • 您可以按照Avner Shahar-Kashtan's answer中的建议将其转换为IList并使用非通用方法。

    IList myList = (IList)Activator.CreateInstance(dynamicClassType);
    
  • 您也可以通过反射调用list-instance的方法。

    // roughly
    MethodInfo addMethod = myList.GetType().GetMethod("Add");
    addMethod.Invoke(myList, objectToAdd);
    
  • 或按Cuong Le's answer中的建议操作,并使用dynamic作为列表实例的类型。

    dynamic myList = Activator.CreateInstance(dynamicClassType);
    

答案 1 :(得分:6)

为了动态构造泛型类型,您必须使用Reflection,特别是MakeGenericType方法。像这样:

Type baseListType = typeof(List<>); // get the generic List<>
Type myType = CompileResultType; // same as in yours.
Type myListType = baseListType.MakeGenericType(myType); // Get the List<MyType>
IList myList = (IList)Activator.CreateInstance(myListType); // Instantiate.

请注意,我将myList定义为IList,因为我们没有编译时类型。幸运的是,我们有方便的基类和接口,如IListIEnumerable和其他几个List<T>实现的接口,我们可以使用它们。

答案 2 :(得分:2)

泛型类型需要一种类,而不是实例,也许你需要:

var myType = CompileResultType();
var listType = typeof (List<>).MakeGenericType(myType);
var myList = Activator.CreateInstance(listType);

但此处的myListobject,如果您想在列表中添加或删除项目,则应该利用dynamic

dynamic myList = Activator.CreateInstance(listType);

所以你可以打电话:

myList.Add(...);

答案 3 :(得分:1)

这将创建列表List<WhatEverIsInMyType>的类型:

var listType = typeof(List<>).MakeGenericType(myType);

现在您需要创建一个实例,但您已经涵盖了:

var list = Activator.CreateInstance(listType);

不幸的是我们正在使用反射,因此在编译时不知道确切的类型,但是并非所有类型都丢失,您可以使用非泛型类型:

    var list = (IList)Activator.CreateInstance(listType);

现在您可以使用Add Remove之类的方法来使用您的列表但要小心,因为如果类型不是数学,您将获得运行时异常。

答案 4 :(得分:0)

<强>分析:

这里的问题是你动态地创建一个类型,并且你没有编译时类型名称来引用它。但是,泛型需要使用类型名称。

假设您想要List<string>string是静态确定的类型名称;你不会先声明一个变量,比如string foo;,然后将你的列表声明为List<foo> ......你会吗?

就像foo一样,myObject不是类型名称 - 它是引用动态类型对象的变量的名称 - 因此您不能将其用作泛型类型参数。同样,List<myType>也不起作用,因为myType也不是类型名称;它只是一个引用Type对象的变量。

<强>建议:

如果你仔细想想,在这里使用泛型只是没有用,因为泛型的使用不会增加静态类型的安全性。只需使用ArrayList代替。

答案 5 :(得分:0)

您使用类型,而非实例。假设CompileResultType()返回MyType

MyType myType = CompileResultType();
List<MyType> list = new List<MyType>();

我不确定你为什么使用Activator.CreateInstance()但是......