动态 List<T> 类型

13

是否有可能在运行时动态设置T类型,并创建一个新的List<T>

谢谢。

5个回答

26

虽然可能可以实现,但并不一定有用,因为你无法将其作为强类型编译代码中的实际使用。创建代码将是:

    Type myType;
    Type listType = typeof(List<>).MakeGenericType(myType);
    IList myList = (IList)Activator.CreateInstance(listType);

3
请注意,“强类型”和“静态类型”之间存在区别。在这里,您将失去静态类型检查,但myList将防止您添加无效的myType实例对象。 - Lee
这对我非常有用,因为我正在编写一个完全动态的数组/列表类型转换器。谢谢! - henon
如果你创建一个“UseAs<T>(T obj)”方法并通过反射调用它并将类型作为参数传递,那么你可以强制使用它。然后在其中你可以做任何事情。也许将其作为本地方法并捕获外部范围?或者传入回调函数。只是说一下,这是可能的。我个人为此编写了一个库。 - Brent Rittenhouse

9

是的。您可以通过反射来实现,使用Type.MakeGenericTypeActivator.CreateInstance

IList MakeListOfType(Type listType)
{
    Type listType = typeof(List<>);
    Type specificListType = listType.MakeGenericType(listType);

    return (IList)Activator.CreateInstance(specificListType);
}

3
你有一个参数列表类型(listType),和一个本地字段列表类型(listType),我想有些人可能会因此感到困惑(我没有投反对票)。 - Martin

1

是的。然而,你无法将它赋值给一个具有通用类型的变量,因为在这种情况下,T直到运行时才会确定。(如果你认为.NET 4.0的协变特性可以帮助你,并允许你将变量声明为,那是不可能的,因为T被List用于in和out两个目的。)

请注意,为了访问“未构造”的通用类型,使用了不寻常的List<>语法。

    public static System.Collections.IList ConstructGenericList(Type t)
    {
        return (System.Collections.IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(t));
    }

1
(关于方差;这仅适用于接口/委托,而不适用于类) - Marc Gravell
@Marc,没错...我应该写成IList<SomeSuperType>。我来改正一下。 - Jason Kresowaty

1

对于DataContractSerializer已知类型,您可能不仅想要提供来自您程序集的类型,还要提供该类型的列表:

public static List<Type> GetKnownTypesForDataContractSerializer()
{
    Assembly a = Assembly.GetExecutingAssembly();
    Type[] array = a.GetExportedTypes();

    List<Type> lista = array.ToList();

    lista = lista.FindAll(item => ((item.IsClass || item.IsEnum) & !item.IsGenericType & !item.IsAbstract == true));



    List<Type> withEnumerable = new List<Type>();
    foreach (Type t in lista)
    {
        withEnumerable.Add(t);   //add basic type

        //now create List<> type
        Type listType = typeof(List<>);
        var listOfType = listType.MakeGenericType(t);

        withEnumerable.Add(listOfType);  //add Type of List<basic type>  
    }

    return withEnumerable;
}

-1

是的,使用泛型,你可以像这样做

    var asd = METHOD<Button>();

    List<t> METHOD<t>()
    {
        return new List<t>();
    }

类型“Button”是硬编码的,这不是运行时。 - Martin
OP要求在运行时确定t的值。在你的例子中,它是在编译时设置的。 - John Buchanan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接