15

If one wants to create a new instance of a generic, the new constraint needs to be defined, like so:

public T SomeMethod<T>() where T : new()
{
    return new T();
}

Is it possible, using reflection, to create an instance of T without the new constraint, like so (contains pseudocode):

public T SomeMethod<T>()
{
    if (T has a default constructor)
    {
        return a new instance of T;
    }
    else
    {
        return Factory<T>.CreateNew();
    }
}
Dave New
  • 38,496
  • 59
  • 215
  • 394
  • Your `a new instance of T` = `new T()' – Nikhil Agrawal Jun 26 '13 at 06:46
  • 2
    Note - you can't satisfy constraints via `if` checked - even if you check that it *has* a constructor, you won't be able to call down into a method that *demands* the `T : new()` constraint, because the compiler *won't believe you* – Marc Gravell Jun 26 '13 at 06:53

3 Answers3

23

Use Activator.CreateInstance() for this. See http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx for more information on how to use this method. Basically, what you do is:

var obj = (T)Activator.CreateInstance(typeof(T));

You can verify whether it has a default constructor by using the GetConstructors() method:

var constructors = typeof(T).GetConstructors();

If you find a constructor that has zero parameters, you can use the Activator.CreateInstance method. Otherwise, you use the Factory<T>.CreateNew() method.

EDIT:

To find out directly whether a constructor without any parameters exist, you can use the following check:

if (typeof(T).GetConstructor(Type.EmptyTypes) != null)
{
    // ...
Pieter van Ginkel
  • 29,160
  • 8
  • 71
  • 111
  • 3
    just on the `GetConstructors()` thing - `typeof(T).GetConstructor(Type.EmptyTypes)` is probably more specific - returns `null` or non-`null`. – Marc Gravell Jun 26 '13 at 06:50
13

Generic methods with a where T : new() constraint implement new T() calls by invoking Activator.CreateInstance<T>(). One interesting thing about this method is that it doesn't include the constraint, so if you are happy to defer the check until runtime, just use:

public T SomeMethod<T>() {
    return Activator.CreateInstance<T>();
}

which will either do exactly what return new T() would have done, or will raise a meaningful exception. Because it handles both the success and failure case, there is no real benefit in doing any additional checks, unless you wanted to do something obscure like not using a constructor at all (which can be done).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • You said: _not using a constructor at all (which can be done)_. Can you please show how that can be done, I mean create instance without using constructor? I want the user of my method to not get null exception when they do `record.SomeColumn`, where `record` is a collection of columns of a db table, and `SomeColumn` is a column, AND there exists no record. Please note that I too don't have (and can't have) the `T : new()` – Sнаđошƒаӽ Mar 01 '18 at 11:05
  • 1
    @Sнаđошƒаӽ `System.Runtime.Serialization.FormatterServices.GetUninitializedObject` - note that an object created in this way can have *completely non-deterministic behaviour*; the typical use case for this is for serialization or ORM libraries when creating POCO/DTO records – Marc Gravell Mar 01 '18 at 11:31
  • Thanks very much. Just one more help please. Is it okay to create an object this way, and then initialize that manually using reflection? As I have already mentioned, when I get no record in DB (I am using Dapper, BTW), I want the returned object to be non-null, but all its properties having their respective default values. Also, can you please tell me where I can learn about the _completely non-deterministic behaviour_? – Sнаđошƒаӽ Mar 01 '18 at 12:05
  • 1
    @Sнаđошƒаӽ by non-deterministic behaviour I mean simply: anything that the constructor would usually have done (like configuring private state): won't have happened. As for "is it OK" - that's massively contextual and depends on the type being created. For a POCO it'll usually work. If you try it with `SqlConnection` or something similar: expect it to fail – Marc Gravell Mar 01 '18 at 12:54
  • Mine is a POCO, so I am safe ;-) Thanks a lot. – Sнаđошƒаӽ Mar 01 '18 at 13:34
1

The last sentence from Marc Gravell's answer (emphasis mine)

...unless you wanted to do something obscure like not using a constructor at all (which can be done)

and from this comment of his, there is an alternative to achieve the same thing. I don't much know which is better performance wise, but honestly, I don't care. If you want to know, follow that link. There author shows a hybrid way.

Use System.Runtime.Serialization.FormatterServices.GetUninitializedObject() (old MSDN documentation link).

public static T SomeMethod<T>()
{
    if (typeof(T) == typeof(string))
    {
        return default(T);
    }

    return (T)FormatterServices.GetUninitializedObject(typeof(T));
}

Note the special care for string. Without that GetUninitializedObject() would fail. This is from MSDN on using this approach on strings:

It does not create an uninitialized string, since creating an empty instance of an immutable type serves no purpose.

It says nothing about why it fails, but more about why it should fail. Immediately after this there is another Note which goes like this:

You cannot use the GetUninitializedObject method to create instances of types that derive from the ContextBoundObject class.

Sнаđошƒаӽ
  • 16,753
  • 12
  • 73
  • 90