Create highly reusable,
type-safe, and efficient code
that works with any data type!
C#
Generics
Keivan Damirchi
Include:
● What is C# Generics?
● When to use C# Generics?
● Benefits & Limitations of Generics
● Constraints in C# Generics
● Covariance & Contravariance in Generics
● Generics with Collections
● Generic Delegates in C#
● Generic Interfaces in C#
● …
What is
C# Generics?
C# Generics are a feature of the C# language
that allow for the creation of reusable, type-safe
code. Generics allow for the creation of classes,
interfaces, and methods that can work with any
data type, rather than being tied to a specific
type. This makes it possible to create more
flexible and reusable code.
1
When to use Generics?
Generics are useful when you need to create
code that can work with different types of
data. They can be used to create reusable
components such as collections, algorithms,
and data structures that can be customized
to work with different types.
Examples:
● A collection class that can hold objects of any
type.
● An algorithm that works on numbers, strings,
or any other type of data.
● A data structure that can be used to store
any type of data.
2
Constraints in C# Generics
Constraints in C# Generics are a way to restrict
the types that can be used with a generic type
or method. For example, if we want to ensure
that a generic type or method can only accept
reference types, we can add the "class"
constraint.
This ensures that only reference types can be used for the type
parameter T. Other constraints include "struct" (which restricts
the type to value types), "new()" (which requires the type to have
a public parameterless constructor), and "base class name"
(which requires the type to derive from a specific base class).
3
Covariance & Contravariance In Generics
Covariance and Contravariance in C# Generics
refer to the ability to use a derived class where a
base class is expected (covariance) or the ability
to use a base class where a derived class is
expected (contravariance). These concepts are
important when working with generic types and
methods that have type parameters that are
used in their return types or parameter types.
In the following code, we have a generic interface
"IAnimalContainer" that has a method "GetAnimal" that
returns an instance of type "Animal":
4
Benefits and Limitations of
C# Generics
The benefits of C# Generics include:
● Type safety: Generics provide compile-time type safety
instead of relying on runtime casting and conversion.
● Reusability: Generic classes and methods reduce
duplicated code by being reusable across different types
and data structures.
● Performance: Generics can improve performance by
eliminating runtime type checking, boxing, and unboxing
operations.
The limitations of C# Generics include:
● Complex code: Generics can make code harder to
understand and maintain.
● Limited constraints: Constraints on generic types are
limited, making it difficult to enforce rules on argument
types.
● Limited covariance/contravariance: Some types can't be
used in a covariant or contravariant manner, limiting
flexibility.
5
Using Generics with Collections
Generics are often used with collections in C#. The
System.Collections.Generic namespace provides a set
of generic collection classes that can be used to store
and manipulate data of a specific type.
For example, the List<T> class can be used to store a list of items of a
specific type:
The Dictionary<TKey, TValue> class can be used to store a set of
key-value pairs of specific types:
Other generic collection classes include Stack<T>, Queue<T>,
HashSet<T>, and LinkedList<T>.
6
Generic Delegates in C#
Delegates are used to define a type-safe function
pointer. In C#, generic delegates can be used to
define a type-safe function pointer that can work
with any type.
For example, the Func<T> delegate is a generic
delegate that can be used to define a function that
returns a value of type T:
The Action<T> delegate is a generic delegate that can be used to
define a function that takes a parameter of type T and returns void:
7
Generic Interfaces in C#
In C#, interfaces can also be made generic.
This allows us to define an interface that can
work with any type.
For example, the IComparable<T> interface can be used to
define a comparison method that can work with any type:
The IEnumerable<T> interface can be used to define an interface for
an object that can be enumerated:
8
C# Generics and design patterns
In C#, interfaces can also be made generic. This
allows us to define an interface that can work with
any type.
9
Reflection and C# Generics
Reflection can be used with generics in C# to
create code that can work with any type.
For example, the Activator.CreateInstance method can be
used to create an instance of any type at runtime.
Generics can be a powerful tool, but they can also make the
code more complex and harder to understand. Keep the code
simple and use generics only when necessary. Avoid
overcomplicating the code with unnecessary generic parameters
and constraints.
10
Generic Classes and
Inheritance in C#
In C#, generic classes can also be used with
inheritance. This allows us to create a base
generic class and derive from it to create a
more specialized generic class.
For example, we can define a generic base class called "List<T>" and
derive from it to create a specialized generic class called "IntList":
11
Generic Methods & Overloading in C#
In C#, we can also use generic methods and
overloading. This allows us to create
methods that can work with any type and
overload them to create specialized
methods for specific types.
For example, we can define a generic method called
"Print<T>" that can print any type:
We can also overload the method to create a specialized
method for a specific type:
12
Boxing and Unboxing in Generics
Boxing and unboxing can occur when using
generics in C#. Boxing is the process of
converting a value type to an object type,
while unboxing is the process of converting
an object type back to a value type.
For example, when using a generic List<int>, if we add a value
of type int to the list, it is automatically boxed into an object:
When retrieving the value from the list, it must be unboxed
back into an int:
13
Anonymous Methods
With C# Generics
Anonymous methods can also be used with
generics in C#. This allows us to define a type-safe
function without having to explicitly define a
delegate type.
For example, we can define an anonymous method that
takes a parameter of type T and returns a value of type
int:
14
Close();
Keivan Damirchi