Activator.CreateInstance - System.Type vs. Generic Method

Daniel Moth asked, in his post, how to choose between a generic type parameter vs. a formal parameter of typed as System.Type. For example, the following two members seem equivalent.

public class Activator {
public static object CreateInstance(Type instanceType);
// or?
public static T CreateInstance<T>();
}

The generic method seems slightly better, as it returns a strongly typed return value. Should you always just use generics in such cases and never have methods that take System.Type?

The answer is no and the reason is that to call a generic method, you have to know the type arguments at compile time, i.e. to call the generic CreateInstance you need to write something like the following (using Foo as the type argument).

Foo foo = Activator.CreateInstance<Foo>();

There are many scenarios where the type argument is not known at compile time, and in such cases System.Type is the way to go.

In case of the Activator, there are actually not that many scenarios when the type argument is known at compile time. If you know that the type argument is Foo, why not just use the Foo’s constructor?

Foo foo = new Foo();

Well, there are some reasons for having Activator.CreateInstace<T> (otherwise we would not have added it), but the scenarios are very rare. Imagine that you have a method that already has a type parameter corresponding to the type that needs to be constructed and the constructor to be invoked takes a parameter:

public static bool StrangeEquals<T>(T instance, params object[] args){
return Activator.CreateInstance<T>(args)).Equals(instance);
}

In this scenario, calling the constructor is not possible because our constraint system does not let you specify that a type argument needs a parameterized constructor. The StranceEquals method could of course use Reflection to invoke the constructor, but Activator.CreateInstace<T> is slightly more convenient.

Now, what about the parameterless CreateInstance<T>? Isn’t is equivalent to saying “new T()”? Yes, in fact the C# complier used Activator.CreateInstance<T> to implement “new T()”. The following code:

static object Bar<T>() where T:new() {
return new T();
}

Gets expanded by the compiler to:

private static object Bar<T>() where T: new() {
return ((default(T) == null) ? Activator.CreateInstance<T>() : default(T));
}