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

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

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)


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
}

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.