How do I create a dynamic type List

2020-02-05 08:50发布

问题:

I don't want my List to be of fixed type. Rather I want the creation of List to be dependent on the type of variable. This code doesn't work:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {

            string something = "Apple";

            Type type = something.GetType();

            List<type> list = null;

            Console.ReadKey();

        }
    }
}

Can anybody tell me what changes I need to make in order to make it work right? I want the creation of list to be dependent on the type of variable something

回答1:

string something = "Apple";
Type type = something.GetType();
Type listType = typeof(List<>).MakeGenericType(new [] { type } );
IList list = (IList)Activator.CreateInstance(listType);

This is how you create a list of statically unknown type. But notice that you are unable to mention the runtime type of the list statically. You have to use a non-generic type or even object.

Without knowing more about what you want to accomplish this is the best you can do.



回答2:

I want type safety but I need dynamic type safety.

If you mean you want runtime type-safety, you can create List<T> using reflection (see usr's answer) or dynamic and then treat it as the non-generic IList.

Using dynamic, it would look something like this:

static List<T> CreateListByExample<T>(T obj)
{
    return new List<T>();
}

…

object something = "Apple";

IList list = CreateListByExample((dynamic)something);

list.Add(something); // OK

list.Add(42);        // throws ArgumentException


回答3:

The dynamic and reflection all work fine - but with a downside on performance - and losing strong typing, code design / clarity etc.
i.e. you should always try and resolve things w/o it - if you can, your code allows it...
So, and (note) depending (very much) on your specific code, needs,
you could also use a 'trick' to 'infer' the type and make it generic...

class Program
{
    static void Main(string[] args)
    {
        string something = "Apple";
        int test = 5;
        var list = something.GetList();
        var listint = test.GetList();
        Console.WriteLine(list.GetType());
    }
}
static class Extension
{
    public static List<T> GetList<T>(this T value)
    {
        return new[] { value }.ToList();
    }
}

...i.e. if you have a value for a variable and before 'entering' the generic context,
you could use extensions (which are very helpful with around this), and let it infer the type and a list type for you
NOTE: this 'work around' unfortunately doesn't always pan out and when your code is 'too dynamic' (I know this is not too 'exact' but out of scope for this) and if it's depending on the reflection induced types etc.
i.e. there isn't a clean-cut solution, this is just an example, you'd need to put some sweat into it :) to make it work for you - e.g. you may require a wrapper type here and there and obviously creating a list in this way might not be what you want etc.



回答4:

The compiler must know the generic type T at compile time. So no, you can't really do this.