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:
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()) }Incompatibility with
struct: You cannot usenew()alongside thestructconstraint because value types automatically possess an implicit parameterless constructor. Thestructconstraint already guarantees instantiation.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);
}
}