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

2019-01-08 02:36发布

问题:

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();

回答1:

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.



回答2:

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()


回答3:

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.



回答4:

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 wont compile as researchEngine doesn't have a public constructor and so cant 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();
        }
    }


回答5:

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
}


回答6:

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();


回答7:

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.



回答8:

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.



回答9:

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.



回答10:

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.