C# where T : new() Constraint: Syntax and Usage
c# where t new: Understand the C# where T : new() constraint: how it requires a parameterless constructor, where it applies, and how to use it safely in generic code.
The C# generic constraint where T : new()—the syntax behind the common search c# where t new—requires that any type argument supplied to a generic type or method expose a public parameterless constructor. This constraint is what allows you to write new T() inside generic code without a cast or reflection call. It is a compile-time guarantee that the type argument can be constructed with no arguments.
What the new() Constraint Requires
The new() constraint is placed on a type parameter after other constraints, if any. It tells the compiler that every type used as T must have a public constructor that takes zero parameters. For value types, this is always true because every struct has an implicit parameterless constructor. For reference types, the rule is stricter: the type must explicitly declare a public parameterless constructor, or it must have no instance constructors at all, in which case the compiler supplies a public one.
public class Widget { public Widget() { } } public class Gadget { public Gadget(string name) { } }
Widget satisfies the new() constraint because it has a public parameterless constructor. Gadget does not, because its only constructor requires a string argument. If you try to use Gadget as a type argument where new() is required, the compiler rejects it.
Applying the Constraint to Classes and Methods
The constraint works on both generic classes and generic methods. Here is a minimal generic class that uses it:
public class Factory<T> where T : new() { public T Create() { return new T(); } }
Inside Create, new T() is legal only because of the new() constraint. Without it, the compiler would report that T cannot be instantiated. The same pattern applies to generic methods:
public static T CreateInstance<T>() where T : new() { return new T(); }
This method can be called with any type that has a public parameterless constructor, such as Widget. It cannot be called with Gadget unless you add a parameterless constructor to Gadget.
Why You Would Use new() in Generic Code
The main reason to use new() is to centralize object creation logic. Instead of requiring callers to pass a factory delegate or using reflection, you can rely on the constraint to guarantee construction is possible. This is common in simple factory methods, dependency resolution helpers, and generic repositories that need to create entity instances.
Consider a generic cache that creates a default value when a key is missing:
public class Cache<T> where T : new() { private readonly Dictionary<string, T> _items = new(); public T GetOrCreate(string key) { if (!_items.TryGetValue(key, out T? value)) { value = new T(); _items[key] = value; } return value; } }
The constraint moves the construction requirement to the type declaration. Callers know immediately that T must be constructible without arguments, and the compiler enforces it at the call site.
Compile-Time Errors and Common Misunderstandings
A frequent mistake is assuming that new() also allows parameterized construction. It does not. new T() always calls the parameterless constructor. If you need to pass arguments, you must use a different approach, such as a Func<T> factory parameter.
Another misunderstanding is that new() can be combined with a base class constraint to create instances of that base type. For example:
public class Repository<T> where T : Entity, new() { public T Create() => new T(); }
This is valid. The type argument must derive from Entity and have a public parameterless constructor. The compiler will enforce both constraints. However, the base class itself cannot be used as T if it is abstract, because abstract classes cannot be instantiated even when they have a parameterless constructor.
A common compile-time error occurs when a type argument has a constructor with optional parameters. In C#, a constructor with all optional parameters is not considered a parameterless constructor for the new() constraint. For example:
public class Sample { public Sample(int value = 0) { } }
Even though new Sample() compiles because of the optional parameter, Sample does not satisfy the new() constraint. The constraint requires a true parameterless constructor, not one that merely can be called with no arguments.
Limitations: Interfaces, Abstract Classes, and Records
Interfaces cannot be used as type arguments with the new() constraint because an interface has no constructor. Abstract classes are also excluded, even if they declare a public parameterless constructor, because they cannot be instantiated directly. The constraint is about the ability to create an instance, not just the presence of a constructor signature.
Records add another edge case. A positional record such as record Person(string Name); has a constructor that requires a string argument, so it does not satisfy new(). You can define a record with a parameterless constructor explicitly, but the primary constructor pattern often conflicts with the constraint. If you need to construct records generically, a factory delegate is usually more practical.
Runtime Behavior and Performance Considerations
new T() is not a direct constructor call in the same way new Widget() is. The runtime must dispatch to the correct constructor based on the actual type argument. This indirection can be more expensive than a direct call, especially in tight loops. The exact cost depends on the runtime and whether the JIT can optimize the call, but you should not assume it is free.
If object creation happens frequently and performance matters, consider caching a factory delegate. For example:
public class Factory<T> where T : new() { private readonly Func<T> _factory = () => new T(); public T Create() => _factory(); }
This still uses new T() inside the lambda, but the delegate is created once and reused. In many cases the JIT can inline or optimize the delegate call better than repeated new T() sites. Measure if this is a real bottleneck; premature optimization is rarely useful.
Alternatives When the Constraint Does Not Fit
When you cannot add a parameterless constructor to a type, or when construction requires parameters, the new() constraint is not the right tool. A common alternative is to pass a factory delegate:
public class Factory<T> { private readonly Func<T> _factory; public Factory(Func<T> factory) { _factory = factory; } public T Create() => _factory(); }
This approach works with any type, regardless of its constructors. The caller decides how to build T:
var factory = new Factory<Gadget>(() => new Gadget("default"));
Another alternative is Activator.CreateInstance<T>(), but that throws at runtime if the type does not have a parameterless constructor. The new() constraint moves that failure to compile time, which is safer. Use new() when the construction contract is fixed and simple; use a factory delegate when you need flexibility or parameterized construction.