Skip to main content

How to Resolve Error "CS0406: The class type constraint 'constraint' must come before any other constraints" in C#

The Compiler Error CS0406 is a syntax error regarding the ordering of Generic Constraints. The message reads: "The class type constraint 'MyBaseClass' must come before any other constraints".

In C#, when defining a generic class or method with the where keyword, there is a strict hierarchy for the constraints. If you require the type parameter T to inherit from a specific Base Class, that class name must be the very first item in the constraint list. Interfaces and the new() constraint must follow afterwards.

This guide explains the required order for generic constraints and how to fix this syntax error.

Understanding Constraint Ordering

C# enforces the following order for the where T : ... clause:

  1. Primary Constraint (The "What is it?" constraint):
    • Must be first.
    • Can be a specific Base Class (e.g., MyClass).
    • OR one of the special keywords: class, struct, notnull, unmanaged.
    • You can only have one primary constraint.
  2. Secondary Constraints (Capabilities):
    • Must come second.
    • Any number of Interfaces (e.g., IEnumerable, IDisposable).
  3. Constructor Constraint:
    • Must be last.
    • The new() keyword.

CS0406 specifically occurs when you list an Interface (Category 2) before the Base Class (Category 1).

Scenario: Placing Interface Before Base Class

This usually happens when you decide to add a base class constraint to an existing generic definition that already had interfaces, and you simply append the class name to the end of the list.

Example of error:

public class User { }
public interface ISerializable { }

// ⛔️ Error CS0406: The class type constraint 'User' must come before any other constraints.
// The compiler requires the concrete class 'User' to be listed before the interface 'ISerializable'.
public class UserManager<T> where T : ISerializable, User
{
public void Process(T user)
{
// ...
}
}

Solution: Reorder the List

To fix the error, move the Base Class name to the immediate right of the colon :.

Solution:

public class User { }
public interface ISerializable { }

// ✅ Correct: Base Class first, Interfaces second.
public class UserManager<T> where T : User, ISerializable
{
public void Process(T user)
{
// ...
}
}
note

Why this rule exists: Since C# does not support multiple inheritance for classes (you can only have one base class), putting the base class first allows the compiler to immediately identify the object's fundamental type structure before processing the interfaces it implements.

Conclusion

CS0406 is purely a formatting rule for generics.

  1. Identify the Class: Look at your where clause. Which identifier represents a Class and which represents an Interface?
  2. Move the Class: Cut the Class name and paste it as the first item in the list.
  3. Order: where T : BaseClass, Interface1, Interface2, new().