If you know the type you actually want (OneMoreClass
) at build time, then you should just use it:
var generic = GenericClass.GetInstance<OneMoreClass>();
But I am assuming you don't know it at build time, and have to get the type
at runtime.
You can do it with reflection, but it isn't pretty, and is slow:
public class GenericClass
{
public static object GetInstance(Type type)
{
var genericType = typeof(GenericClass<>).MakeGenericType(type);
return Activator.CreateInstance(genericType);
}
}
Since you don't know the resulting type at build time, you can't return anything but object
(or dynamic
) from the method.
Here is how much slower (for 100,000 creates)
public class GenericClass
{
public static object GetInstance(Type type)
{
var genericType = typeof(GenericClass<>).MakeGenericType(type);
return Activator.CreateInstance(genericType);
}
public static GenericClass<T> GetInstance<T>()
where T : class
{
return new GenericClass<T>();
}
}
[Test]
public void CanMakeGenericViaReflection_ButItsSlow()
{
var timer = new Stopwatch();
var SC = new SomeClass();
SC.TypeOfAnotherClass = typeof(OneMoreClass);
timer.Start();
for (int x = 0; x < 100000; x++)
{
GenericClass.GetInstance(SC.TypeOfAnotherClass);
}
timer.Stop();
Console.WriteLine("With Reflection: " + timer.ElapsedMilliseconds + "ms.");
timer.Restart();
for (int x = 0; x < 100000; x++)
{
GenericClass.GetInstance<OneMoreClass>();
}
timer.Stop();
Console.WriteLine("Without Reflection: " + timer.ElapsedMilliseconds + "ms.");
}
Results:
With Reflection: 243ms.
Without Reflection: 2ms.
So a little over 100x slower.
The real thing to note about generics is that the <T>
s in generics are resolved at build-time by the C# compiler, and the real class names are inserted. When you have to defer that until run-time, you end up paying the performance price.