How to Resolve Error "CS0702: Constraint cannot be special class 'identifier'" in C#
The Compiler Error CS0702 is a restriction error regarding Generic Constraints. The message reads: "Constraint cannot be special class 'System.Object' (or ValueType, Array, etc.)".
In C#, generic constraints (where T : BaseClass) allow you to restrict a generic parameter to a specific inheritance tree. However, certain fundamental types in the .NET framework—specifically System.Object, System.ValueType, and System.Array—are considered "special." You cannot use them as explicit base class constraints because C# provides specific keywords (like class and struct) to handle these cases, or because the runtime does not support constraining to that specific type.
This guide explains which types are restricted and the correct keywords to use instead.
Understanding Special Classes
C# constraints are designed to be specific.
System.Object: Since every type in .NET inherits from Object, a constraint ofwhere T : Objectwould accept absolutely anything. This is redundant and semantically identical to having no constraint at all.System.ValueType: This is the base class for all structs. C# provides thestructkeyword to enforce value types. Using the class name directly is forbidden to avoid syntax confusion.System.Array: Arrays have special runtime handling. You generally cannot constrain a genericTto be "An Array class" directly via inheritance syntax.
Scenario 1: Constraining to System.Object
This error occurs when developers try to be explicit that T must be an object, or perhaps they intend to restrict T to Reference Types but use the wrong syntax.
Example of error
// ⛔️ Error CS0702: Constraint cannot be special class 'object'
public class Container<T> where T : System.Object
{
}
Solution: Use class or Remove Constraint
If you want to allow anything (Reference or Value types), simply remove the constraint.
// ✅ Correct: Accepts any type (int, string, custom classes)
public class Container<T>
{
}
If you specifically want to restrict T to Reference Types (classes, strings, interfaces), use the class keyword.
// ✅ Correct: Restricts T to reference types only
public class ReferenceContainer<T> where T : class
{
}
Scenario 2: Constraining to System.ValueType
You might want to ensure that T is a simple type like int, bool, or a custom struct. Writing where T : System.ValueType seems logical because all structs inherit from it, but C# enforces the use of the struct keyword instead.
Example of error
using System;
// ⛔️ Error CS0702: Constraint cannot be special class 'ValueType'
public class StructProcessor<T> where T : ValueType
{
}
Solution: Use struct or unmanaged
Use the struct constraint (or unmanaged in newer C# versions) to enforce value types.
// ✅ Correct: 'struct' implies inheriting from System.ValueType
public class StructProcessor<T> where T : struct
{
public T Create()
{
return default(T);
}
}
Scenario 3: Constraining to System.Array
You might want to write a generic method that only accepts arrays. However, System.Array is restricted from being a generic constraint base class.
Example of error
using System;
public class ArrayHelper
{
// ⛔️ Error CS0702: Constraint cannot be special class 'Array'
public void Process<T>(T array) where T : Array
{
}
}
Solution: Use Collection Interfaces
Instead of constraining to the base class Array, allow the method to accept generic collections or IEnumerable.
Option A: Specific Array Parameter
If you only want arrays, don't constrain T to be an array; make the parameter an array of T.
public class ArrayHelper
{
// ✅ Correct: The method takes T[], so implicit type is the element, not the array.
public void Process<T>(T[] array)
{
Console.WriteLine($"Array length: {array.Length}");
}
}
Option B: Generic Interfaces
Use IList<T>, ICollection<T>, or IEnumerable<T>.
using System.Collections.Generic;
public class ArrayHelper
{
// ✅ Correct: Arrays implement IEnumerable<T>
public void Process<T>(IEnumerable<T> collection)
{
foreach (var item in collection) { /*...*/ }
}
}
System.Enum and System.Delegate:
In older versions of C#, System.Enum and System.Delegate also triggered CS0702.
However, since C# 7.3, constraints like where T : System.Enum and where T : System.Delegate are valid. If you see CS0702 for these types, you need to upgrade your project to use a newer language version (C# 7.3 or later).
Conclusion
CS0702 enforces the use of specific C# keywords over raw CLR type names for constraints.
- Object: Use no constraint, or use
where T : class. - ValueType: Use
where T : struct. - Array: Use
T[]as the parameter type or use interfaces likeIEnumerable<T>. - Enum/Delegate: Update to C# 7.3+ to allow these constraints.