13

Is it possible to create a new List<T> where the T is dynamically set at runtime?

Cheers

0

5 Answers 5

26

It's possible, but not necessarily useful, since you couldn't actually use it from compiled code as strongly typed. The creation code would be

    Type myType;
    Type listType = typeof(List<>).MakeGenericType(myType);
    IList myList = (IList)Activator.CreateInstance(listType);
Sign up to request clarification or add additional context in comments.

3 Comments

Please note there is a difference between 'strongly-typed' and 'statically-typed'. You lose static type checking here but myList will prevent you from adding objects which are not valid myType instances.
It is very useful to me since I am writing a completely dynamic array/list type converter. Thanks!
You CAN use it strongly typed if you make a "UseAs<T>(T obj)" method and call THAT via reflection and passing in the type as the argument. Then inside that you can do whatever. Maybe make it a local method and capture your outside scope? Or.. pass in a callback. Just saying, it's possible. I made a library for this personally.
9

Yes. You can do this via Reflection, using Type.MakeGenericType and Activator.CreateInstance.

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

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

1 Comment

you have a parameter listType and a local field listType, I imagine some people would be confused by that (I didn't downvote)
1

Yes. However, you won't be able to assign it to a variable that has a generic type since the T in this case will not be decided until runtime. (If you are thinking that the .NET 4.0 covariance feature will help you and let you declare the variable as IList<SomeSuperType>, it won't as the T is used by List<T> for both in and out purposes.)

Note the unusual List<> syntax in order to access the "unconstructed" generic type.

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

2 Comments

(re variance; that also only works for interfaces / delegates; not classes)
@Marc, right... I should have wrote IList<SomeSuperType>. Fixing.
1

For DataContractSerializer Known Types you may want to supply not only types from your assembly but also list of that types:

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;
}

Comments

-1

yes using generic you can do something like this

    var asd = METHOD<Button>();

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

2 Comments

the type "Button" is hardcoded, that's not runtime
the OP asked for the t to be determined at runtime. In your example, its set at compile time.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.