Activator.CreateInstance<T> – 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));
}

Comments (9)

  1. kfarmer says:

    One thing I’ve had to wrestle with recently was how to differentiate between the following:

    T Foo<T>()

    object Foo(Type)

    The only way I saw in the API was to rely on the detail that the generic method just happened to have an empty parameter list. But what if they were:

    T Foo<T>(string)

    object Foo(string)

    Any thoughts?

  2. I’ve used the Activator.CreateInstance<T>() method in class that takes in a System.Data.IDataReader and creates an object of the correct type based on a O/R mapping.

    The method was something like this:

    public sealed class EntityFactory

    {

    public T CreateEntity<T>(IDataReader reader) where T: new()

    {

    T t = Activator.CreateInstance<T>();

    // Do the mapping

    return t;

    }

    }

    For me, the caller of this method knows the type it tries to create at compile time, so it matches my need perfectly.

    Person p = EntityFactory.CreateEntity<Person>(personReader);

  3. TAG says:

    This is lame example !

    You definitely need generic Activator. But it must not be blind search-and-replace.

    You need to create

    public static T CreateInstance<T>(Type instanceType);

    This T param must check if instanceType is correct one (i.e. inherit from T) before invoking any contructors.

    Actualy this is somethat tricky issue – as not much value added – but

    public static T CreateInstance<T>(String assembly, String typeName) is clearly needed. And there is nothing about knowing your type in compile time. ‘object’ is useless for developers. First thing that they do – they cast !

    Take a read my suggestion on ProductFeedback on this matter http://lab.msdn.com/productfeedback/viewfeedback.aspx?feedbackid=FDBK21541

  4. Krzysztof Cwalina says:

    TAG, why is casting so much worse in this example? The only difference seems to be slightly different calling syntax.

    (Foo)Create(typeof(Bar)) // vs.

    Create<Foo>(typeof(Bar))

    In both cases users will get an exception when created type does not match the expected type.

    I actually think the non-generic method is better for late bound sceanrios. The generic one has to throw, which is slow. The non-generic one returns the created type and the caller can either cast (which throws) or use the is/as operators which are very fast.

  5. What about generating stuff from Reflection.Emit?

    I can’t find a way to find call a method with a generic argument with Reflection.Emit.

    public void bar<T>()

    {

    }

    public void foo<J>()

    {

    bar<J>();

    }

    I have bar, but how do I create foo?

  6. TAG says:

    Krzysztof,

    IMHO, This is too late to check if contructed object has correct type after contruction was complete.

  7. TAG says:

    P.S> Create(typeof(Bar)) is simply subset of my proposal – Create<object>(typeof(Bar)) will do same trick with "is/as"

  8. JD says:

    So TAG, it seems you want something like this:

    T CreateInstance<T>(string typeName)

    where T : new()

    {

    Type desiredType = typeof(T);

    Type actualType = Type.GetType(typeName);

    if (!desiredType.IsAssignableFrom(actualType))

    throw YouDirtyRatException();

    return new T();

    }

    object CreateInstance( string typeName, Type desiredType)

    {

    Type actualType = Type.GetType(typeName);

    if (!desiredType.IsAssignableFrom(actualType))

    throw YouDirtyRatException();

    return Activator.CreateInstance(actualType);

    }

    …which seems pretty easy to implement yourself…

  9. Rafael says:

    Well, the problem isnt that…

    An example is an application i have some time ago that im trying to port to the new framework version.

    On this application, my dinamically created objects have need parameters on those constructors, but, using generics i dont have any chance to cast .ctor(object1, object2).

    Even in Activator.CreateInstanc<T>() i cant call the default constructor.

    The way i resolved that is that my T have to be of determined type, this type must have the variable needed in the old constructor.

    So my snippet is like this:

    public static T CreateDefaultInstance(Connection cn)

    {

       T t = new T();

       t.Connection = cn;

       return t;

    }

    There is another way i just realized, this can be:

    public static T CreateInstance (Connection con)

    {

       T t = (T)Activator.CreateInstance(typeof(T), new object[]{con});

    }

    But i have another problem.

    How to create a new object when we dont need its type?

    Suppose we have this:

    public static T CreateInstance(Connection con)

    {

    }

    static void Main()

    {

       string type = "System.String";

       Type t = Type.GetType (type);

       CreateInstance<t>(null);

    }

    I dont have a way to use this approach.