The new() Constraint in C# Generics Explained

The new() constraint in C# is a generic type constraint that requires any type argument substituted for a type parameter to have a public, parameterless constructor. This article explains what the new() constraint does, demonstrates how to implement it in generic classes and methods, details the syntax rules and limitations, and shows how it enables safe object instantiation at compile time.

What Is the new() Constraint?

In C# generics, the compiler prevents you from directly instantiating a type parameter (such as writing T item = new T();) because it cannot guarantee that the type supplied at runtime will have a callable constructor.

By applying the where T : new() constraint, you guarantee to the compiler that the type T provides an accessible, parameterless constructor. This allows you to instantiate T directly inside generic classes, structs, or methods.

Basic Syntax and Implementation

To apply the constraint, append the where clause to your generic class, interface, or method declaration:

public class Factory<T> where T : new()
{
    public T CreateInstance()
    {
        // Allowed because of the new() constraint
        return new T();
    }
}

When consuming this generic class, the type argument passed to T must have a public parameterless constructor:

public class Product
{
    public string Name { get; set; } = "Default";

    // Public parameterless constructor
    public Product() { }
}

public class CustomProduct
{
    // Only has a parameterized constructor
    public CustomProduct(string name) { }
}

// Valid: Product has a public parameterless constructor
Factory<Product> validFactory = new Factory<Product>();
Product product = validFactory.CreateInstance();

// Compile Error: CustomProduct does not have a public parameterless constructor
// Factory<CustomProduct> invalidFactory = new Factory<CustomProduct>();

Rules and Placement

When using the new() constraint, several language rules must be followed:

  1. Ordering Among Multiple Constraints: When a type parameter has multiple constraints, new() must always be specified last.

    public class EntityStore<T> where T : class, IComparable<T>, new()
    {
        // Correct order: primary constraint (class), interface, constructor (new())
    }
  2. Incompatibility with struct: You cannot use new() alongside the struct constraint because value types automatically possess an implicit parameterless constructor. The struct constraint already guarantees instantiation.

  3. Cannot Be Used with Abstract Types: Even if an abstract class contains a parameterless constructor, it cannot satisfy the new() constraint because abstract classes cannot be directly instantiated.

Limitations and Workarounds

The new() constraint only supports parameterless constructors; C# does not provide a native constraint for constructors that accept parameters (e.g., new(int, string)).

If your generic logic requires creating instances using parameterized constructors, pass a factory delegate such as Func<T> or a dedicated factory interface instead of relying on the new() constraint:

public class ParameterizedFactory<T>
{
    private readonly Func<string, T> _creator;

    public ParameterizedFactory(Func<string, T> creator)
    {
        _creator = creator;
    }

    public T Create(string parameter)
    {
        return _creator(parameter);
    }
}