477

I'm trying to create a new object of type T via its constructor when adding to the list.

I'm getting a compile error: The error message is:

'T': cannot provide arguments when creating an instance of a variable

But my classes do have a constructor argument! How can I make this work?

public static string GetAllItems<T>(...) where T : new()
{
   ...
   List<T> tabListItems = new List<T>();
   foreach (ListItem listItem in listCollection) 
   {
       tabListItems.Add(new T(listItem)); // error here.
   } 
   ...
}
Rup
  • 33,765
  • 9
  • 83
  • 112
LB.
  • 13,730
  • 24
  • 67
  • 102
  • 2
    possible duplicate of [Create instance of generic type?](http://stackoverflow.com/questions/731452/create-instance-of-generic-type) – nawfal Apr 23 '13 at 07:23
  • 2
    Proposal to get this functionality into the language: https://github.com/dotnet/roslyn/issues/2206 – Ian Kemp Jan 13 '17 at 10:43
  • 1
    In Microsoft's documentation, see [Compiler Error CS0417](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs0417). – DavidRR Nov 27 '17 at 21:28
  • 2
    Proposal to get this functionality into the language was moved to: https://github.com/dotnet/csharplang/issues/769 – reducing activity Mar 25 '20 at 00:22

16 Answers16

447

In order to create an instance of a generic type in a function you must constrain it with the "new" flag.

public static string GetAllItems<T>(...) where T : new()

However that will only work when you want to call the constructor which has no parameters. Not the case here. Instead you'll have to provide another parameter which allows for the creation of object based on parameters. The easiest is a function.

public static string GetAllItems<T>(..., Func<ListItem,T> del) {
  ...
  List<T> tabListItems = new List<T>();
  foreach (ListItem listItem in listCollection) 
  {
    tabListItems.Add(del(listItem));
  }
  ...
}

You can then call it like so

GetAllItems<Foo>(..., l => new Foo(l));
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • How would this work when called internally from a generic class? I have posted my code in an answer below. I don't know the concrete class internally, as it's a generic class. Is there a way round this. I dont want to use the other suggestion of using property initialiser syntax as that will bypass the logic I have in the constructor – ChrisCa Nov 05 '09 at 16:28
  • added my code to another question http://stackoverflow.com/questions/1682310/c-generics-problem-newing-up-the-generic-type-with-parameters-in-the-construct – ChrisCa Nov 05 '09 at 17:59
  • 1
    Thanks. In my case I know the constructor's argument(s) when I call the method, I just needed to get around the Type parameter's limitation that it could not be constructed with parameters, so I used a [thunk](http://en.wikipedia.org/wiki/Thunk_%28functional_programming%29). The thunk is an optional parameter to the method, and I only use it if provided: `T result = thunk == null ? new T() : thunk();` The benefit of this for me is consolidating the logic of `T` creation in one place rather than sometimes creating `T` inside and sometimes outside of the method. – Carl G May 13 '12 at 23:18
373

in .Net 3.5 and after you could use the activator class:

(T)Activator.CreateInstance(typeof(T), args)
MikeT
  • 5,398
  • 3
  • 27
  • 43
user287107
  • 9,286
  • 1
  • 31
  • 47
  • 1
    we could also use expression tree to build the object – Welly Tambunan Jan 18 '13 at 03:07
  • 6
    What is args? an object[]? – Rodney P. Barbati May 14 '13 at 16:32
  • 6
    Yes, args is an object[] where you specify the values to be provided to the T's constructor: "new object[]{ par1, par2 }" – Niki Romagnoli Dec 03 '13 at 14:56
  • 1
    If you can use "where T : SomeBaseClass", then you can maintain type safety when using an object[] by creating a "public static object[] GetArgs" method on SomeBaseClass with a list of parameters matching the constructor you want to use, then use the value returned from that as your "args" variable. – kevinpo Mar 11 '14 at 14:49
  • 51
    _[Cautionary conclusion would be that **Activator.CreateInstance is taking roughly 11 times as much time to do the same job as a new T() does**, and a delegate takes roughly 1.5 times as much. If you have a performance problem, first measure to see where your bottleneck is. Yes, the above timings might indicate that Activator.CreateInstance has more overhead than a dynamically built delegate, but there might be much bigger fish to fry in your codebase before you get (or even have to get) to this level of optimization](http://tinyurl.com/oyewrf5)_ –  Mar 19 '15 at 05:21
  • I found I had an error and needed to do this: Activator.CreateInstance(typeof(T), args) as T – chris31389 Nov 06 '15 at 11:48
  • @chris31389 this only works for nullable types, so in a template the type T must contain some constraints. I can't imagine where the direct cast does not work, only in an error case if the object cannot be created. – user287107 Nov 08 '15 at 11:04
  • 11
    WARNING: If you have a dedicated constructor just for the sake of `Activator.CreateInstance` for this one thing, It will look like your constructor isn't used at all, and somebody might try to "clean up" and delete it (to cause a runtime error at some random time in the future). You may want to consider adding a dummy function where you use this constructor just so you get a compile error if you try to delete it. – jrh Oct 04 '17 at 19:12
53

Since nobody bothered to post the 'Reflection' answer (which I personally think is the best answer), here goes:

public static string GetAllItems<T>(...) where T : new()
{
   ...
   List<T> tabListItems = new List<T>();
   foreach (ListItem listItem in listCollection) 
   {
       Type classType = typeof(T);
       ConstructorInfo classConstructor = classType.GetConstructor(new Type[] { listItem.GetType() });
       T classInstance = (T)classConstructor.Invoke(new object[] { listItem });

       tabListItems.Add(classInstance);
   } 
   ...
}

Edit: This answer is deprecated due to .NET 3.5's Activator.CreateInstance, however it is still useful in older .NET versions.

James Jones
  • 8,653
  • 6
  • 34
  • 46
  • My understanding is that most of the performance hit is in acquiring the ConstructorInfo in the first place. Don't take my word for it without profiling it. If that is the case, simply storing the ConstructorInfo for later reuse could alleviate the performance hit of repeated instantiations through reflection. – Kelsie Apr 24 '12 at 04:33
  • 1
    @James I agree, I was surprised not to see this as the "answer". In fact, I searched on this question expecting to find a nice easy example (like yours) since it's been so long since I've done reflection. Anyway, +1 from me, but +1 on the Activator answer too. I looked into what Activator is doing, and it turns out that what is does is some very well engineered reflection. :) – Mike Jan 30 '13 at 06:01
  • The GetConstructor() call is expensive, so it is worth caching before the loop. This way, by calling only Invoke() inside the loop, it is a lot faster than calling both or even using Activator.CreateInstance(). – Cosmin Rus Nov 08 '18 at 13:26
  • 1
    Performance concerns aside, this is not typesafe as everything is resolved at runtime. If the `classType` constructor changes, e.g. to become a list of `IFoo` rather than a list of concrete `Foo`, then the compiler won't give us any help at all. Things will continue to compile and you'll crash at runtime – Orion Edwards May 16 '23 at 20:41
36

Very old question, but new answer ;-)

The ExpressionTree version: (I think the fastests and cleanest solution)

Like Welly Tambunan said, "we could also use expression tree to build the object"

This will generate a 'constructor' (function) for the type/parameters given. It returns a delegate and accept the parameter types as an array of objects.

Here it is:

// this delegate is just, so you don't have to pass an object array. _(params)_
public delegate object ConstructorDelegate(params object[] args);

public static ConstructorDelegate CreateConstructor(Type type, params Type[] parameters)
{
    // Get the constructor info for these parameters
    var constructorInfo = type.GetConstructor(parameters);

    // define a object[] parameter
    var paramExpr = Expression.Parameter(typeof(Object[]));

    // To feed the constructor with the right parameters, we need to generate an array 
    // of parameters that will be read from the initialize object array argument.
    var constructorParameters = parameters.Select((paramType, index) =>
        // convert the object[index] to the right constructor parameter type.
        Expression.Convert(
            // read a value from the object[index]
            Expression.ArrayAccess(
                paramExpr,
                Expression.Constant(index)),
            paramType)).ToArray();

    // just call the constructor.
    var body = Expression.New(constructorInfo, constructorParameters);

    var constructor = Expression.Lambda<ConstructorDelegate>(body, paramExpr);
    return constructor.Compile();
}

Example MyClass:

public class MyClass
{
    public int TestInt { get; private set; }
    public string TestString { get; private set; }

    public MyClass(int testInt, string testString)
    {
        TestInt = testInt;
        TestString = testString;
    }
}

Usage:

// you should cache this 'constructor'
var myConstructor = CreateConstructor(typeof(MyClass), typeof(int), typeof(string));

// Call the `myConstructor` function to create a new instance.
var myObject = myConstructor(10, "test message");

enter image description here


Another example: passing the types as an array

var type = typeof(MyClass);
var args = new Type[] { typeof(int), typeof(string) };

// you should cache this 'constructor'
var myConstructor = CreateConstructor(type, args);

// Call the `myConstructor` fucntion to create a new instance.
var myObject = myConstructor(10, "test message");

DebugView of Expression

.Lambda #Lambda1<TestExpressionConstructor.MainWindow+ConstructorDelegate>(System.Object[] $var1) {
    .New TestExpressionConstructor.MainWindow+MyClass(
        (System.Int32)$var1[0],
        (System.String)$var1[1])
}

This is equivalent to the code that is generated:

public object myConstructor(object[] var1)
{
    return new MyClass(
        (System.Int32)var1[0],
        (System.String)var1[1]);
}

Small downside

All valuetypes parameters are boxed when they are passed like an object array.


Simple performance test:

private void TestActivator()
{
    Stopwatch sw = Stopwatch.StartNew();
    for (int i = 0; i < 1024 * 1024 * 10; i++)
    {
        var myObject = Activator.CreateInstance(typeof(MyClass), 10, "test message");
    }
    sw.Stop();
    Trace.WriteLine("Activator: " + sw.Elapsed);
}

private void TestReflection()
{
    var constructorInfo = typeof(MyClass).GetConstructor(new[] { typeof(int), typeof(string) });

    Stopwatch sw = Stopwatch.StartNew();
    for (int i = 0; i < 1024 * 1024 * 10; i++)
    {
        var myObject = constructorInfo.Invoke(new object[] { 10, "test message" });
    }

    sw.Stop();
    Trace.WriteLine("Reflection: " + sw.Elapsed);
}

private void TestExpression()
{
    var myConstructor = CreateConstructor(typeof(MyClass), typeof(int), typeof(string));

    Stopwatch sw = Stopwatch.StartNew();

    for (int i = 0; i < 1024 * 1024 * 10; i++)
    {
        var myObject = myConstructor(10, "test message");
    }

    sw.Stop();
    Trace.WriteLine("Expression: " + sw.Elapsed);
}

TestActivator();
TestReflection();
TestExpression();

Results:

Activator: 00:00:13.8210732
Reflection: 00:00:05.2986945
Expression: 00:00:00.6681696

Using Expressions is +/- 8 times faster than Invoking the ConstructorInfo and +/- 20 times faster than using the Activator

Jeroen van Langen
  • 21,446
  • 3
  • 42
  • 57
  • Do you have any insight on what to do if you want to construct MyClass with the constructor public MyClass(T data). In this case, Expression.Convert throws an exception and if I use the generic constraint base class to convert to, then Expression.New throws because the constructor info is for a generic type – Mason Mar 08 '17 at 17:46
  • 1
    @Mason (took a while to answer ;-)) `var myConstructor = CreateConstructor(typeof(MyClass), typeof(int));` this is working fine. I don't know. – Jeroen van Langen Mar 21 '20 at 01:23
33

Object initializer

If your constructor with the parameter isn't doing anything besides setting a property, you can do this in C# 3 or better using an object initializer rather than calling a constructor (which is impossible, as has been mentioned):

public static string GetAllItems<T>(...) where T : new()
{
   ...
   List<T> tabListItems = new List<T>();
   foreach (ListItem listItem in listCollection) 
   {
       tabListItems.Add(new T() { YourPropertyName = listItem } ); // Now using object initializer
   } 
   ...
}

Using this, you can always put any constructor logic in the default (empty) constructor, too.

Activator.CreateInstance()

Alternatively, you could call Activator.CreateInstance() like so:

public static string GetAllItems<T>(...) where T : new()
{
   ...
   List<T> tabListItems = new List<T>();
   foreach (ListItem listItem in listCollection) 
   {
        object[] args = new object[] { listItem };
        tabListItems.Add((T)Activator.CreateInstance(typeof(T), args)); // Now using Activator.CreateInstance
   } 
   ...
}

Note that Activator.CreateInstance can have some performance overhead that you may want to avoid if execution speed is a top priority and another option is maintainable to you.

Community
  • 1
  • 1
Tim Lehner
  • 14,813
  • 4
  • 59
  • 76
  • 1
    this prevents `T` from protecting it's invariants (given that `T` has >0 dependencies or required values, you can now create instances of `T` that are in an invalid/unusable state. unless `T` is something dead simple like a DTO och viewmodel, I'd say avoid this. – sara Apr 07 '16 at 06:58
  • This also requires properties not being encapsulated. – Guney Ozsan Oct 28 '22 at 15:26
20

This will not work in your situation. You can only specify the constraint that it has an empty constructor:

public static string GetAllItems<T>(...) where T: new()

What you could do is use property injection by defining this interface:

public interface ITakesAListItem
{
   ListItem Item { set; }
}

Then you could alter your method to be this:

public static string GetAllItems<T>(...) where T : ITakesAListItem, new()
{
   ...
   List<T> tabListItems = new List<T>();
   foreach (ListItem listItem in listCollection) 
   {
       tabListItems.Add(new T() { Item = listItem });
   } 
   ...
}

The other alternative is the Func method described by JaredPar.

Garry Shutler
  • 32,260
  • 12
  • 84
  • 119
  • this would bypass any logic that is in the constructor that takes the arguments though, right? I would like to do something Like Jared's approach but am calling the method internally within the class so don't know what the concrete type is...hmmm – ChrisCa Nov 05 '09 at 16:21
  • 3
    Right, this calls the logic of the T() default constructor, then simply sets the property "Item". If you're trying to invoke the logic of a non-default constructor, this will not help you. – Scott Stafford Feb 25 '10 at 15:01
8

If you simply want to initialise a member field or property with the constructor parameter, in C# >= 3 you can do it very easier:

public static string GetAllItems<T>(...) where T : InterfaceOrBaseClass, new() 
{ 
   ... 
   List<T> tabListItems = new List<T>(); 
   foreach (ListItem listItem in listCollection)  
   { 
       tabListItems.Add(new T{ BaseMemberItem = listItem }); // No error, BaseMemberItem owns to InterfaceOrBaseClass. 
   }  
   ... 
} 

This is the same thing Garry Shutler said, but I'd like to put an aditional note.

Of course you can use a property trick to do more stuff than just setting a field value. A property "set()" can trigger any processing needed to setup its related fields and any other need for the object itself, including a check to see if a full initialization is to take place before the object is used, simulating a full contruction (yes, it is an ugly workaround, but it overcomes M$'s new() limitation).

I can't be assure if it is a planned hole or an accidental side effect, but it works.

It is very funny how MS people adds new features to the language and seems to not do a full side effects analysis. The entire generic thing is a good evidence of this...

Mike Chamberlain
  • 39,692
  • 27
  • 110
  • 158
fljx
  • 151
  • 1
  • 2
  • 1
    Both constraints are needed. InterfaceOrBaseClass makes the compiler aware of the field/property BaseMemberItem. If the "new()" constraint is commented, it will trigger the error: Error 6 Cannot create an instance of the variable type 'T' because it does not have the new() constraint – fljx Apr 30 '10 at 19:40
7

I found that I was getting an error "cannot provide arguments when creating an instance of type parameter T" so I needed to do this:

var x = Activator.CreateInstance(typeof(T), args) as T;
chris31389
  • 8,414
  • 7
  • 55
  • 66
7

If you have access to the class you're going to use, you can use this approach which I used.

Create an interface that has an alternative creator:

public interface ICreatable1Param
{
    void PopulateInstance(object Param);
}

Make your classes with an empty creator and implement this method:

public class MyClass : ICreatable1Param
{
    public MyClass() { //do something or nothing }
    public void PopulateInstance (object Param)
    {
        //populate the class here
    }
}

Now use your generic methods:

public void MyMethod<T>(...) where T : ICreatable1Param, new()
{
    //do stuff
    T newT = new T();
    T.PopulateInstance(Param);
}

If you don't have access, wrap the target class:

public class MyClass : ICreatable1Param
{
    public WrappedClass WrappedInstance {get; private set; }
    public MyClass() { //do something or nothing }
    public void PopulateInstance (object Param)
    {
        WrappedInstance = new WrappedClass(Param);
    }
}
Daniel Möller
  • 84,878
  • 18
  • 192
  • 214
7

You need to add where T: new() to let the compiler know that T is guaranteed to provide a default constructor.

public static string GetAllItems<T>(...) where T: new()
Richard
  • 1,169
  • 6
  • 8
  • 2
    UPDATE: The correct error message is: 'T': cannot provide arguments when creating an instance of a variable – LB. May 08 '09 at 15:11
  • That's because you're not using a blank constructor, you're passing an argument to it of object. There's no way it can handle that without specifying that the generic Type has a new(object) parameter. – Min May 08 '09 at 15:14
  • Then you'll need to either: 1. Use reflection 2. Pass the parameter into an initialization method instead of the constructor, where the initialization method belongs to an interface that your type implements and which is included in the where T: ... declaration. Option 1 is the lowest impact for the rest of your code, but option 2 provides compile time checking. – Richard May 08 '09 at 15:14
  • Don't use reflection! There are other ways as outlined in other answers that get you the same effect. – Garry Shutler May 08 '09 at 15:17
  • @Garry - I'd agree that reflection isn't necessarily the best approach, but it does allow you to achieve what's required with minimal change to the rest of the code base. That said, I do much prefer the factory delegate approach from @JaredPar. – Richard May 08 '09 at 15:22
  • If really need pass parameter then use reflection, if you aren't then use @richards example. eg. CurrentDataStore[UnitOfWorkDataStore.DATA_CONTEXT_KEY] = new T(); works perfectly. to create a new EF dataContext – Nickz May 13 '11 at 02:57
4

Using the static abstract interface methods feature in C# 11 it is possible to build a workaround, using a factory pattern. For example:

public interface IFactory<TSelf> where TSelf : IFactory<TSelf> {
  static abstract TSelf New(int i, string s);
}

public struct Foo : IFactory<Foo> {

  public static Foo New(int i, string s) {
    return new Foo(i, s);
  }

  public readonly int I;
  public readonly string S;

  public Foo(int i, string s) {
    I = i;
    S = s;
  }
}

public static class Maker {
  public static T Make<T>(int i, string s) where T : IFactory<T> {
    return T.New(i, s);
  }
}

A limitation of this approach is that it can only be used on classes that you own, since you need to implement your specific factory interface on the target classes.

kolis
  • 415
  • 5
  • 10
0

This is kind of mucky, and when I say kind of mucky I may mean revolting, but supposing you can furnish your parameterised type with an empty constructor, then:

public static T GetTInstance<T>() where T: new()
{
    var constructorTypeSignature = new Type[] {typeof (object)};
    var constructorParameters = new object[] {"Create a T"};
    return (T) new T().GetType().GetConstructor(constructorTypeSignature).Invoke(constructorParameters);
}

Will effectively allow you to construct an object from a parameterised type with an argument. In this case I am assuming the constructor I want has a single argument of type object. We create a dummy instance of T using the constraint permitted empty constructor and then use reflection to get one of its other constructors.

Silas Davis
  • 712
  • 1
  • 9
  • 15
0

I sometimes use an approach that resembles to the answers using property injection, but keeps the code cleaner. Instead of having a base class/interface with a set of properties, it only contains a (virtual) Initialize()-method that acts as a "poor man's constructor". Then you can let each class handle it's own initialization just as a constructor would, which also adds a convinient way of handling inheritance chains.

If often find myself in situations where I want each class in the chain to initialize its unique properties, and then call its parent's Initialize()-method which in turn initializes the parent's unique properties and so forth. This is especially useful when having different classes, but with a similar hierarchy, for example business objects that are mapped to/from DTO:s.

Example that uses a common Dictionary for initialization:

void Main()
{
    var values = new Dictionary<string, int> { { "BaseValue", 1 }, { "DerivedValue", 2 } };

    Console.WriteLine(CreateObject<Base>(values).ToString());

    Console.WriteLine(CreateObject<Derived>(values).ToString());
}

public T CreateObject<T>(IDictionary<string, int> values)
    where T : Base, new()
{
    var obj = new T();
    obj.Initialize(values);
    return obj;
}

public class Base
{
    public int BaseValue { get; set; }

    public virtual void Initialize(IDictionary<string, int> values)
    {
        BaseValue = values["BaseValue"];
    }

    public override string ToString()
    {
        return "BaseValue = " + BaseValue;
    }
}

public class Derived : Base
{
    public int DerivedValue { get; set; }

    public override void Initialize(IDictionary<string, int> values)
    {
        base.Initialize(values);
        DerivedValue = values["DerivedValue"];
    }

    public override string ToString()
    {       
        return base.ToString() + ", DerivedValue = " + DerivedValue;
    }
}
Anders
  • 734
  • 8
  • 12
0

If all is you need is convertion from ListItem to your type T you can implement this convertion in T class as conversion operator.

public class T
{
    public static implicit operator T(ListItem listItem) => /* ... */;
}

public static string GetAllItems(...)
{
    ...
    List<T> tabListItems = new List<T>();
    foreach (ListItem listItem in listCollection) 
    {
        tabListItems.Add(listItem);
    } 
    ...
}
NightmareZ
  • 41
  • 5
-1

Supplementary performance information

Performance test of database access and filling of data model class with the expression method of Jeroen van Langen (see above) and direct instantiation of the data model class.

Conclusion: The expression method is faster.

Results:

  1. Test: direct instance of data model class: Records: 3558, seconds: 1.2746019
  2. Test: instance with method read list with type parameter: records: 3558, seconds: 0.4878858

Code example of the expression method:

var list = ReadList<DataModel>(SQLStatement, Connection);

Method ReadList: Note: all data model class has a constructor with parameter type of SQLDataReader

public static List<pDataModel> ReadList<pDataModel>(string pSQLStatement, SqlConnection pConnection) where pDataModel : new()
    {
            // constructor of data model
            var lType = typeof(pDataModel);
            var lParameters = new Type[] { typeof(SqlDataReader) };
            var lDataModelConstructor = CreateConstructor(lType, lParameters);

            // read data
            List<pDataModel> lDataList = new List<pDataModel>();
            using (pConnection)
            {
                SqlCommand lCommand;
                lCommand = new SqlCommand(pSQLStatement, pConnection);
                pConnection.Open();
                SqlDataReader lReader = lCommand.ExecuteReader();


                if (lReader.HasRows)
                {
                    while (lReader.Read())
                    {
                        pDataModel lDataItem = (pDataModel)lDataModelConstructor(lReader);
                        lDataList.Add(lDataItem);
                    }
                }
                lReader.Close();
                pConnection.Close();
            }

            return lDataList;
    }

Code example of the direct instantiation:

           List<DataModel> list= new List<DataModel>();
            using (connection)
            {
                SqlCommand command;
                command = new SqlCommand(SQLStatement, connection);
                connection.Open();
                SqlDataReader reader = command.ExecuteReader();
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        list.Add(new DataModel(reader));
                    }
                }
                reader.Close();
                connection.Close();
            }
Franz
  • 77
  • 1
  • 4
-3

I believe you have to constraint T with a where statement to only allow objects with a new constructor.

RIght now it accepts anything including objects without it.

klkitchens
  • 1,202
  • 2
  • 16
  • 39
  • 3
    You may want to change this answer because this got edited into the question after you answered which leaves this answer out of context. – shuttle87 Oct 16 '15 at 17:08