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
How to Run a C# Console Application with the Console Hidden
How to Change the File Location Programmatically
Load Local HTML File in a C# Webbrowser
Swashbuckle - Add Model and Example Values to Swagger Ui from a Model from Another Project
Using C++ Class Dll in C# Application
How to Customize the System Menu of a Windows Form
Recursively Get Properties & Child Properties of a Class
How to Write to the Console in Colour in .Net
Is It Safe to Check Floating Point Values for Equality to 0
Generic Constraint to Match Numeric Types
How to Loop Through Items in a List Box and Then Remove Those Item
C# Winforms Combobox Dynamic Autocomplete
Open File with Associated Application
Remove HTML Tags from String Including &Nbsp in C#