C# Create New T()

C# Create New T()

Take a look at new Constraint

public class MyClass<T> where T : new()
{
protected T GetObject()
{
return new T();
}
}

T could be a class that does not have a default constructor: in this case new T() would be an invalid statement. The new() constraint says that T must have a default constructor, which makes new T() legal.

You can apply the same constraint to a generic method:

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

If you need to pass parameters:

protected T GetObject(params object[] args)
{
return (T)Activator.CreateInstance(typeof(T), args);
}

C# create Object obj = new T()?

Lee's answer is correct.

The reason is that in order to be able to call new T() you need to add a new() constraint to your type parameter:

void Add<T>() where T : new()
{
... new T() ...
}

You also need a constraint T : A so that you can add your object of type T to a List<A>.

Note: When you use new() together with other contraints, the new() constraint must come last.

Related

  • Constraints on Type Parameters

Create a new instance of T without the new constraint

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)
{
// ...

Generic T - create new instance

In DeserializeObject<T> you are calling

GetDefault<T>()

which has the type parameter constraint where T : new(), but DeserializeObject<T>'s T is unconstrained. You have to add the constraint to DeserializeObject<T> as well:

internal static T DeserializeObject<T>(this JsonSerializer serializer, string value) : where T : new()

How to initialize generic parameter type T?

You have two options:

You can constrain T: you do this by adding: where T : new() to your method. Now you can only use the someMethod with a type that has a parameterless, default constructor (see Constraints on Type Parameters).

Or you use default(T). For a reference type, this will give null. But for example, for an integer value this will give 0 (see default Keyword in Generic Code).

Here is a basic console application that demonstrates the difference:

using System;

namespace Stackoverflow
{
class Program
{
public static T SomeNewMethod<T>()
where T : new()
{
return new T();
}

public static T SomeDefaultMethod<T>()
where T : new()
{
return default(T);
}

struct MyStruct { }

class MyClass { }

static void Main(string[] args)
{
RunWithNew();
RunWithDefault();
}

private static void RunWithDefault()
{
MyStruct s = SomeDefaultMethod<MyStruct>();
MyClass c = SomeDefaultMethod<MyClass>();
int i = SomeDefaultMethod<int>();
bool b = SomeDefaultMethod<bool>();

Console.WriteLine("Default");
Output(s, c, i, b);
}

private static void RunWithNew()
{
MyStruct s = SomeNewMethod<MyStruct>();
MyClass c = SomeNewMethod<MyClass>();
int i = SomeNewMethod<int>();
bool b = SomeNewMethod<bool>();

Console.WriteLine("New");
Output(s, c, i, b);
}

private static void Output(MyStruct s, MyClass c, int i, bool b)
{
Console.WriteLine("s: " + s);
Console.WriteLine("c: " + c);
Console.WriteLine("i: " + i);
Console.WriteLine("b: " + b);
}

}
}

It produces the following output:

New
s: Stackoverflow.Program+MyStruct
c: Stackoverflow.Program+MyClass
i: 0
b: False
Default
s: Stackoverflow.Program+MyStruct
c:
i: 0
b: False

Create instance of generic type whose constructor requires a parameter?

Additionally a simpler example:

return (T)Activator.CreateInstance(typeof(T), new object[] { weight });

Note that using the new() constraint on T is only to make the compiler check for a public parameterless constructor at compile time, the actual code used to create the type is the Activator class.

You will need to ensure yourself regarding the specific constructor existing, and this kind of requirement may be a code smell (or rather something you should just try to avoid in the current version on c#).

Create an instance of the variable type 'T'

Your code doesn't compile. I can't imagine why you would want to do what you are trying to do. But the closest you can get to a legitimate implementation is:

class Program
{
static void Main(string[] args)
{
List<ColorPoint> colorList = new List<ColorPoint>(4);
AddPoint<ColorPoint>(colorList);
}

public static List<T> AddPoint<T>(List<T> pointList)
where T : Point, new()
{
pointList.Add(new T());
return pointList;
}
}

public class Point
{
double x; // Position x
double y; // Position y

public Point() : this(0, 0)
{
}

public Point(double pos_x, double pos_y) // Constructor
{
this.x = pos_x;
this.y = pos_y;
}
}

public class ColorPoint : Point
{
double color; // White value (0 to 255)

public ColorPoint()
{
}

public ColorPoint(double pos_x, double pos_y) : base(pos_x, pos_y)
{
}
}

public class AmountPoint : Point
{
int amount; // Amount of Persons standing at this point

public AmountPoint()
{
}

public AmountPoint(double pos_x, double pos_y) : base(pos_x, pos_y)
{
}
}

What does where T : class, new() mean?

That is a constraint on the generic parameter T. It must be a class (reference type) and must have a public parameter-less default constructor.

That means T can't be an int, float, double, DateTime or any other struct (value type).

It could be a string, or any other custom reference type, as long as it has a default or parameter-less constructor.

Generic method add new T to list of T

I think your calling code looks like

 void Method<T>(ObservedList<T> bayList)
{
SetBayNumb<T>(bayList);
}

Issue come from the fact there is no restrictions on T in Method and hence compiler can't match arguments for SetBayNumb.

Note that generic type name is just name - you can pick any name you like and it could help with reasoning about error. Rewriting the same method with differently named generic argument like:

 void Method<TArg>(ObservedList<TArg> bayList)
{
SetBayNumb<TArg>(bayList);
}

gives better error:

The type 'TArg' must have a public parameterless constructor in order to use it as parameter 'T' in the generic type or method

Notice that there are 2 different types involved in the error (which is hard to see when both called the same "T").

Fixes:

  • specify the same restrictions on outer generic method (Method<TArg>(ObservedList<TArg> bayList) where TArg : ... new() )
  • specify T on generic class level instead of individual method
  • pass concrete class that satisfy both requirements (class for items in the list should implement interface and have parameterless constructor).


Related Topics



Leave a reply



Submit