I have a little problem for you guys.
I would like to do this:
Type[] classes = new Type[]{ Class1, Class2 };
foreach(Type t in classes){
List<t> list = new List<t>();
}
Is there some way to do this?
You cannot cast to a generic type at runtime, because the type in the generic needs to be resolved at compile time.
You can create a generic type in a dynamic manner using reflection, but unless you hard-code the cast, all you get in return is an object.
I cannot really tell what it is you want, I have to agree with a comment this is an XY problem. I would be inclined to make the presumptuous statement that there is a design issue somewhere that this is trying to solve, instead of addressing the design issue directly, or asking the question of what you are trying to achieve directly.
You can use the following code to create the type, then the dynamic
type can be used to duck type the various members of List<T>
without knowing/caring that it is a list or what T
is:
using System;
using System.Collections.Generic;
namespace ConsoleApplication61
{
class Program
{
static void Main(string[] args)
{
dynamic o = CreateGeneric(typeof(List<>), typeof(int));
o.Add(1);
Console.WriteLine(o[0]);
Console.Read();
}
public static object CreateGeneric(Type generic, Type innerType, params object[] args)
{
System.Type specificType = generic.MakeGenericType(new System.Type[] { innerType });
return Activator.CreateInstance(specificType, args);
}
}
}
The above sample duck types the Add
method and the Indexer. The DLR does the type handling and the duck typing at runtime - knowing that 1
is an int
, for example.
Just to clarify, I likely wouldn't use such code in production (unless you requirements are very specific to need this) and any issues with type-mismatching will occur at run time; so you either need to type very accurately (limited IntelliSense) or have good error handling.
Thanks to this blog post for the CreateGeneric
method.
This assumes .NET 4 with the new CLR. As @MartinLiversage has also pointed out, this particular sample assumes that you are utilising the list in a sort-of-strongly-typed manner. In my example I am passing an int
to a List<int>
hidden in a dynamic
.
We have been on .NET 4 almost since it was released. We have a large application with an even larger code base. dynamic
isn't used once in the application, and only a few times in the test code base. That isn't to say "don't use it", it's to say "most of the time, you don't need it".
You can do it like this:
foreach(Type t in classes)
{
var listType = typeof(List<>).MakeGenericType(t);
var instance = Activator.CreateInstance(listType);
}
This is possible with the Type.MakeGenericType Method
Here's a nifty method I found that should work for ya: CodeRef
public static object CreateGeneric(Type generic, Type innerType, params object[] args)
{
System.Type specificType = generic.MakeGenericType(new System.Type[] { innerType });
return Activator.CreateInstance(specificType, args);
}
And use it like so:
var o = CreateGeneric(typeof(List<>), t);
Unfortunately, to add items you'll have to do it like so (where item is the item you're adding).
MethodInfo addMethod = o.GetType().GetMethod("Add");
addMethod.Invoke(o, new object[] { item.ToType(t) });
Or use the Generic
type as mentioned in another answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With