C#
new operator
generic types
programming
C# tutorials

C Create New T

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In C#, new T() inside generic code allows creation of an instance of a type parameter. This works only when the type parameter has the new() constraint, which guarantees a public parameterless constructor. The feature is useful for factories, serializers, and framework infrastructure that must create unknown concrete types safely.

The new() Generic Constraint

Without constraints, the compiler cannot assume T is instantiable. The new() constraint tells the compiler that T has an accessible no argument constructor.

csharp
1using System;
2
3public static class Factory
4{
5    public static T Create<T>() where T : new()
6    {
7        return new T();
8    }
9}
10
11public class UserSettings
12{
13    public string Theme { get; set; } = "light";
14}
15
16public class Program
17{
18    public static void Main()
19    {
20        UserSettings settings = Factory.Create<UserSettings>();
21        Console.WriteLine(settings.Theme);
22    }
23}

If T lacks a public parameterless constructor, this code will not compile.

Where new T() Works Well

This pattern is strong when object creation is simple and invariant free. It avoids reflection overhead and keeps type safety at compile time. Examples include plugin registries, test data scaffolding, and generic containers that need default instances.

For richer construction logic, inject a factory delegate instead of forcing all types to expose a no argument constructor.

csharp
1using System;
2
3public static class BetterFactory
4{
5    public static T Create<T>(Func<T> creator)
6    {
7        return creator();
8    }
9}
10
11public class ConnectionConfig
12{
13    public string Host { get; }
14
15    public ConnectionConfig(string host)
16    {
17        Host = host;
18    }
19}
20
21public class Program
22{
23    public static void Main()
24    {
25        var cfg = BetterFactory.Create(() => new ConnectionConfig("db.internal"));
26        Console.WriteLine(cfg.Host);
27    }
28}

This preserves constructor invariants and supports immutable models.

new T() Versus Reflection

Reflection based creation with Activator.CreateInstance is more flexible but slower and more failure prone at runtime. new T() with constraints catches invalid usage at compile time and communicates intent clearly.

Use reflection only when type identity is unknown until runtime and cannot be represented through generic constraints or injected factories.

API Design Guidance

When exposing generic APIs, avoid unnecessary new() constraints because they can force awkward constructors on domain types. Add the constraint only when your method genuinely needs to create instances.

If a type requires mandatory constructor parameters for correctness, prefer a delegate factory or dependency injection container integration.

Testing, DI, And Framework Usage

In testing frameworks, new T() is sometimes used to create default fixtures for many type arguments. This is convenient for smoke tests, but it can hide missing required state. Balance convenience with explicit factory setup for cases where object validity depends on constructor inputs.

Dependency injection systems usually reduce the need for direct new T() calls in application services. Instead of constructing dependencies manually, services request interfaces and let the container resolve concrete implementations. Keep new T() usage mostly in infrastructure utilities, not in domain orchestration logic.

If you expose extensibility points to third party users, document constructor expectations clearly. The new() constraint communicates compile time requirements, but users still need guidance on default property values and initialization order for meaningful runtime behavior.

When documenting public generic APIs, include concrete examples for both successful and failing type arguments so consumers understand exactly when the new() constraint applies.

Common Pitfalls

  • Adding new() constraints to APIs that never instantiate T.
  • Forcing domain types to include meaningless parameterless constructors.
  • Assuming new T() can call non public constructors.
  • Mixing new() constraints with reflection without clear need.
  • Ignoring constructor invariants for immutable or validated models.

Summary

  • new T() requires where T : new() in generic code.
  • It gives compile time safety for simple object creation.
  • Delegate factories are better for complex constructors.
  • Reflection is more dynamic but less safe and often slower.
  • Choose the creation strategy based on invariants and API ergonomics.

Course illustration
Course illustration

All Rights Reserved.