Tutorialsteacher

Follow Us

Articles
  • C#
  • C# OOP
  • ASP.NET Core
  • ASP.NET MVC
  • LINQ
  • Inversion of Control (IoC)
  • Web API
  • JavaScript
  • TypeScript
  • jQuery
  • Angular 11
  • Node.js
  • D3.js
  • Sass
  • Python
  • Go lang
  • HTTPS (SSL)
  • Regex
  • SQL
  • SQL Server
  • PostgreSQL
  • MongoDB
  • C# - Get Started
  • C# - Version History
  • C# - First Program
  • C# - Keywords
  • C# - Class and Objects
  • C# - Namespace
  • C# - Variables
  • C# - Implicitly-Typed Variables
  • C# - Data Types
  • Numbers
  • Strings
  • DateTime
  • Structure
  • Enum
  • StringBuilder
  • Anonymous Types
  • Dynamic Types
  • Nullable Types
  • C# - Value & Reference Types
  • C# - Interface
  • C# - Operators
  • C# - if else Statements
  • C# - Ternary Operator ?:
  • C# - Switch
  • C# - For Loop
  • C# - While Loop
  • C# - Do-while Loop
  • C# - Partial Class
  • C# - Static
  • C# - Array
  • Multidimensional Array
  • Jagged Array
  • C# - Indexer
  • C# - Generics
  • Generic Constraints
  • C# - Collections
  • ArrayList
  • List
  • SortedList
  • Dictionary
  • Hashtable
  • Stack
  • Queue
  • C# - Tuple
  • C# - ValueTuple
  • C# - Built-in Exceptions
  • Exception Handling
  • throw
  • Custom Exception
  • C# - Delegates
  • Func Delegate
  • Action Delegate
  • Predicate Delegate
  • Anonymous Methods
  • C# - Events
  • C# - Covariance
  • C# - Extension Method
  • C# - Stream I/O
  • C# - File
  • C# - FileInfo
  • C# - Object Initializer
  • OOP - Overview
  • Object-Oriented Programming
  • Abstraction
  • Encapsulation
  • Association & Composition
  • Inheritance
  • Polymorphism
  • Method Overriding
  • Method Hiding
  • C# - Solid Principles
  • Single Responsibility Principle
  • Open/Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle
  • Design Patterns
  • Singleton
  • Abstract Factory
  • Factory Method
Entity Framework Extensions - Boost EF Core 9
  Bulk Insert
  Bulk Delete
  Bulk Update
  Bulk Merge

C# Generic Constraints

C# allows you to use constraints to restrict client code to specify certain types while instantiating generic types. It will give a compile-time error if you try to instantiate a generic type using a type that is not allowed by the specified constraints.

You can specify one or more constraints on the generic type using the where clause after the generic type name.

Syntax:
GenericTypeName<T> where T  : contraint1, constraint2

The following example demonstrates a generic class with a constraint to reference types when instantiating the generic class.

Example: Declare Generic Constraints
class DataStore<T> where T : class
{
    public T Data { get; set; }
}

Above, we applied the class constraint, which means only a reference type can be passed as an argument while creating the DataStore class object. So, you can pass reference types such as class, interface, delegate, or array type. Passing value types will give a compile-time error, so we cannot pass primitive data types or struct types.

DataStore<string> store = new DataStore<string>(); // valid
DataStore<MyClass> store = new DataStore<MyClass>(); // valid
DataStore<IMyInterface> store = new DataStore<IMyInterface>(); // valid
DataStore<IEnumerable> store = new DataStore<IMyInterface>(); // valid
DataStore<ArrayList> store = new DataStore<ArrayList>(); // valid
//DataStore<int> store = new DataStore<int>(); // compile-time error

The following table lists the types of generic constraints.

ConstraintDescription
classThe type argument must be any class, interface, delegate, or array type.
class?The type argument must be a nullable or non-nullable class, interface, delegate, or array type.
structThe type argument must be non-nullable value types such as primitive data types int, char, bool, float, etc.
new()The type argument must be a reference type which has a public parameterless constructor. It cannot be combined with struct and unmanaged constraints.
notnullAvailable C# 8.0 onwards. The type argument can be non-nullable reference types or value types. If not, then the compiler generates a warning instead of an error.
unmanagedThe type argument must be non-nullable unmanged types.
base class nameThe type argument must be or derive from the specified base class. The Object, Array, ValueType classes are disallowed as a base class constraint. The Enum, Delegate, MulticastDelegate are disallowed as base class constraint before C# 7.3.
<base class name>?The type argument must be or derive from the specified nullable or non-nullable base class
<interface name>The type argument must be or implement the specified interface.
<interface name>?The type argument must be or implement the specified interface. It may be a nullable reference type, a non-nullable reference type, or a value type
where T: UThe type argument supplied for T must be or derive from the argument supplied for U.

where T : struct

The following example demonstrates the struct constraint that restricts type argument to be non-nullable value type only.

Example: struct Constraints
class DataStore<T> where T : struct
{
    public T Data { get; set; }
}

DataStore<int> store = new DataStore<int>(); // valid
DataStore<char> store = new DataStore<char>(); // valid
DataStore<MyStruct> store = new DataStore<MyStruct>(); // valid
//DataStore<string> store = new DataStore<string>(); // compile-time error 
//DataStore<IMyInterface> store = new DataStore<IMyInterface>(); // compile-time error 
//DataStore<ArrayList> store = new DataStore<ArrayList>(); // compile-time error

where T : new()

The following example demonstrates the struct constraint that restricts type argument to be non-nullable value type only.

Example: new() Constraint
class DataStore<T> where T : class, new()
{
    public T Data { get; set; }
}

DataStore<MyClass> store = new DataStore<MyClass>(); // valid
DataStore<ArrayList> store = new DataStore<ArrayList>(); // valid
//DataStore<string> store = new DataStore<string>(); // compile-time error 
//DataStore<int> store = new DataStore<int>(); // compile-time error 
//DataStore<IMyInterface> store = new DataStore<IMyInterface>(); // compile-time error

where T : baseclass

The following example demonstrates the base class constraint that restricts type argument to be a derived class of the specified class, abstract class, or an interface.

Example: BaseClass Constraint
class DataStore<T> where T : IEnumerable
{
    public T Data { get; set; }
}

DataStore<ArrayList> store = new DataStore<ArrayList>(); // valid
DataStore<List> store = new DataStore<List>(); // valid
//DataStore<string> store = new DataStore<string>(); // compile-time error 
//DataStore<int> store = new DataStore<int>(); // compile-time error 
//DataStore<IMyInterface> store = new DataStore<IMyInterface>(); // compile-time error 
//DataStore<MyClass> store = new DataStore<MyClass>(); // compile-time error
TUTORIALSTEACHER.COM

TutorialsTeacher.com is your authoritative source for comprehensive technologies tutorials, tailored to guide you through mastering various web and other technologies through a step-by-step approach.

Our content helps you to learn technologies easily and quickly for learners of all levels. By accessing this platform, you acknowledge that you have reviewed and consented to abide by our Terms of Use and Privacy Policy, designed to safeguard your experience and privacy rights.

[email protected]

ABOUT USTERMS OF USEPRIVACY POLICY
copywrite-symbol

2024 TutorialsTeacher.com. (v 1.2) All Rights Reserved.