Course contentsShow
← C#
Lesson 267 of 1,9083. Generics and Collections ArchitectureFree lesson

Default Constraint Usage

Implement the new() constraint to permit the instantiation of generic types within a factory pattern.

In this lesson, you will learn how to use the new() constraint to enable generic classes to instantiate objects without knowing their specific types at compile time.

The Problem: Creating Instances in Generics

Normally, if you have a generic class like Factory<T>, you cannot simply write T item = new T();. This is because the C# compiler doesn’t know if T has a public parameterless constructor. It must assume T could be anything—perhaps an interface or a class that requires specific arguments—so it prevents you from trying to instantiate it directly.

The Solution: The new() Constraint

To tell the compiler that it is safe to instantiate T, we use the new() constraint. This constraint acts as a promise: you are telling the compiler, "I guarantee that any type passed as T will have a public, parameterless constructor."

Here is how you implement it in a simple factory pattern:

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

// Usage:
var factory = new Factory<List<string>>();
List<string> list = factory.CreateInstance();

Why use this?

This pattern is incredibly powerful when building decoupled systems. By using the new() constraint, your factory can create any object type without being tied to specific implementations. This keeps your architecture flexible. If you try to pass a type that doesn't have a parameterless constructor (such as a class that only has a constructor requiring arguments), the compiler will throw an error immediately, maintaining your type safety while providing the flexibility of a factory.

Remember that the new() constraint must always be the last constraint if you are using multiple constraints (e.g., where T : IEntity, new()). This ensures that your generic components remain predictable and robust.

Key Takeaway: The new() constraint informs the compiler that a generic type parameter has a parameterless constructor, allowing you to instantiate that type safely within your generic classes.