ChatGPT解决这个技术问题 Extra ChatGPT

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

Can you please explain to me what where T : class, new() means in the following line of code?

void Add<T>(T item) where T : class, new();
Does this answer your question? What does new() mean?

T
Tohid

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.


Just to clarify, if you don't have the class clause as part of the where T..., then it is safe to use int, float, double etc.
@AboutDev correct, you don't have to put constraints on your generic type parameter. But if you are creating a generic that expects to only work on reference or value types, then you should specify. Without a constraint, you can expect reference types (classes) or value types (structs (int, float, double...)).
What about where T : [interface name], new() ? Do you still need to have a parameter-less constructor?
To clarify Justin's comment, an empty constructor has no statements (like the default constructor) while a parameterless constructor may contain statements (like initializing a list).
@VinceTino: new() precisely specifies "must have a public parameterless constructor"
J
Justin Niessner

Those are generic type constraints. In your case there are two of them:

where T : class

Means that the type T must be a reference type (not a value type).

where T : new()

Means that the type T must have a parameter-less constructor. Having this constraint will allow you to do something like T field = new T(); in your code which you wouldn't be able to do otherwise.

You then combine the two using a comma to get:

where T : class, new()

Good points for second and third, just to add information, I think second point is useful when doing reflection in generic type. eg. T t = new T(); t.GetType().GetProperty("ID").SetValue(t, uniqueId, null);
I believe it is redundant to say where T : class, new(), since new() already implies class because structs cannot have default constructors.
@DharmaTurtle, "structs can't contain explicit parameterless constructors", doesn't mean that they don't have one, it says that you can't define one. source : msdn.microsoft.com/tr-tr/library/aa288208(v=vs.71).aspx
A
Abhinav

where T : struct

The type argument must be a value type. Any value type except Nullable can be specified. See Using Nullable Types (C# Programming Guide) for more information.

where T : class

The type argument must be a reference type, including any class, interface, delegate, or array type. (See note below.)

where T : new() The type argument must have a public parameterless constructor. When used in conjunction with other constraints, the new() constraint must be specified last.

where T : [base class name]

The type argument must be or derive from the specified base class.

where T : [interface name]

The type argument must be or implement the specified interface. Multiple interface constraints can be specified. The constraining interface can also be generic.

where T : U

The type argument supplied for T must be or derive from the argument supplied for U. This is called a naked type constraint.

(Original Source: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters)


This was useful, but link to source.
S
Sergio

class & new are 2 constraints on the generic type parameter T.
Respectively they ensure:

class

The type argument must be a reference type; this applies also to any class, interface, delegate, or array type.

new

The type argument must have a public parameterless constructor. When used together with other constraints, the new() constraint must be specified last.

Their combination means that the type T must be a Reference Type (can't be a Value Type), and must have a parameterless constructor.

Example:

struct MyStruct { } // structs are value types

class MyClass1 { } // no constructors defined, so the class implicitly has a parameterless one

class MyClass2 // parameterless constructor explicitly defined
{
    public MyClass2() { }
}

class MyClass3 // only non-parameterless constructor defined
{
    public MyClass3(object parameter) { }
}

class MyClass4 // both parameterless & non-parameterless constructors defined
{
    public MyClass4() { }
    public MyClass4(object parameter) { }
}

interface INewable<T>
    where T : new()
{
}

interface INewableReference<T>
    where T : class, new()
{
}

class Checks
{
    INewable<int> cn1; // ALLOWED: has parameterless ctor
    INewable<string> n2; // NOT ALLOWED: no parameterless ctor
    INewable<MyStruct> n3; // ALLOWED: has parameterless ctor
    INewable<MyClass1> n4; // ALLOWED: has parameterless ctor
    INewable<MyClass2> n5; // ALLOWED: has parameterless ctor
    INewable<MyClass3> n6; // NOT ALLOWED: no parameterless ctor
    INewable<MyClass4> n7; // ALLOWED: has parameterless ctor

    INewableReference<int> nr1; // NOT ALLOWED: not a reference type
    INewableReference<string> nr2; // NOT ALLOWED: no parameterless ctor
    INewableReference<MyStruct> nr3; // NOT ALLOWED: not a reference type
    INewableReference<MyClass1> nr4; // ALLOWED: has parameterless ctor
    INewableReference<MyClass2> nr5; // ALLOWED: has parameterless ctor
    INewableReference<MyClass3> nr6; // NOT ALLOWED: no parameterless ctor
    INewableReference<MyClass4> nr7; // ALLOWED: has parameterless ctor
}

Good Demonstration. Thanks.
b
bad_coder

new(): Specifying the new() constraint means type T must use a parameterless constructor, so an object can be instantiated from it - see Default constructors.

class: Means T must be a reference type so it can't be an int, float, double, DateTime or other struct (value type).

public void MakeCars()
{
    //This won't compile as researchEngine doesn't have a public constructor and so can't be instantiated.
    CarFactory<ResearchEngine> researchLine = new CarFactory<ResearchEngine>();
    var researchEngine = researchLine.MakeEngine();

    //Can instantiate new object of class with default public constructor
    CarFactory<ProductionEngine> productionLine = new CarFactory<ProductionEngine>();
    var productionEngine = productionLine.MakeEngine();
}

public class ProductionEngine { }
public class ResearchEngine
{
    private ResearchEngine() { }
}

public class CarFactory<TEngine> where TEngine : class, new()
{
    public TEngine MakeEngine()
    {
        return new TEngine();
    }
}

E
Evan Mulawski

That means that type T must be a class and have a constructor that does not take any arguments.

For example, you must be able to do this:

T t = new T();

not just a constructor, but a constructor that takes no arguments.
@NerdFury: Thanks. That is an important bit. Corrected.
M
Mong Zhu

where (C# Reference)

The new() Constraint lets the compiler know that any type argument supplied must have an accessible parameterless--or default-- constructor

So it should be, T must be a class, and have an accessible parameterless--or default constructor.


O
Otman IGHOULASSEN

What comes after the "Where" is a constraint on the generic type T you declared, so:

class means that the T should be a class and not a value type or a struct.

new() indicates that the T class should have a public parameter-free default constructor defined.


佚名

It's called a 'constraint' on the generic parameter T. It means that T must be a reference type (a class) and that it must have a public default constructor.


P
Peter Lillevold

This is part of the Generics mechanism, where the where keyword add constraints to what types must implement in order to be used as type parameters.


R
Rebwar

when using the class in constraints it's mean you can only use Reference type, another thing to add is when to use the constraint new(), it's must be the last thing you write in the Constraints terms.