Generics in C#: Complete Beginner to Advanced Guide
Generics are one of the most powerful features available in C#. They allow developers to write reusable, type-safe, and efficient code without sacrificing performance.
Before generics were introduced, developers often relied on object-based collections, which required casting and increased the risk of runtime errors. Generics solve these problems by allowing types to be specified at compile time.
In this guide, you'll learn how generics work, when to use them, how to create generic classes and methods, and how generic collections improve application development.
- What Are Generics?
- Why Use Generics?
- Generic Classes
- Generic Methods
- Generic Collections
- Generic Constraints
- Multiple Type Parameters
- Performance Benefits
- Common Mistakes
- Best Practices
What Are Generics?
Generics allow classes, methods, interfaces, and delegates to operate with type parameters instead of specific data types.
Instead of creating separate implementations for integers, strings, or custom objects, one generic implementation can work with all of them.
```
public class Box<T>
{
public T Value { get; set; }
}
```
The type parameter T acts as a placeholder that
will be replaced with a concrete type when the class is used.
Why Use Generics?
- Improved type safety.
- Reduced code duplication.
- Better performance.
- Compile-time validation.
- Cleaner and more maintainable code.
Creating a Generic Class
```
public class Box<T>
{
public T Value { get; set; }
}
Box<string> messageBox =
new Box<string>();
messageBox.Value =
"Hello World";
Box<int> numberBox =
new Box<int>();
numberBox.Value = 100;
```
The same class works with different types without requiring multiple implementations.
Generic Methods
Methods can also use type parameters.
```
public static void Display<T>(T value)
{
Console.WriteLine(value);
}
Display("Hello");
Display(100);
Display(true);
```
The compiler automatically determines the correct type.
Understanding List<T>
One of the most common generic collections is List<T>.
```
List<string> names =
new List<string>();
names.Add("John");
names.Add("Jane");
```
The list only accepts strings because the generic type is specified as string.
Understanding Dictionary<TKey, TValue>
Dictionaries use two generic type parameters.
```
Dictionary<int, string>
students =
new Dictionary<int, string>();
students.Add(1, "John");
students.Add(2, "Sarah");
```
The key must be an integer and the value must be a string.
Multiple Type Parameters
```
public class Pair<TKey, TValue>
{
public TKey Key { get; set; }
public TValue Value { get; set; }
}
Pair<int, string> item =
new Pair<int, string>();
item.Key = 1;
item.Value = "Laptop";
```
Generic Constraints
Constraints limit the types that can be used with generics.
```
public class Repository<T>
where T : class
{
}
```
The constraint above ensures that only reference types can be used.
Other common constraints include:
- where T : class
- where T : struct
- where T : new()
- where T : BaseClass
- where T : InterfaceName
Performance Benefits
Generics avoid boxing and unboxing operations when working with value types.
```
List<int> numbers =
new List<int>();
```
Because the collection stores integers directly, additional conversions are unnecessary.
Generics and Repository Pattern
Generics are commonly used in repository implementations.
```
public interface IRepository<T>
{
Task<T> GetByIdAsync(int id);
Task AddAsync(T entity);
}
```
This allows the same repository structure to work with multiple entity types.
Common Beginner Mistakes
- Using object instead of generics.
- Ignoring generic constraints.
- Creating unnecessary generic types.
- Using overly complex type parameters.
- Not leveraging generic collections.
Best Practices
- Use meaningful type parameter names.
- Apply constraints when appropriate.
- Prefer generic collections.
- Keep generic designs simple.
- Use generics for reusable components.
Frequently Asked Questions
What does T mean in generics?
T stands for Type and represents a placeholder for a data type.
Are generics faster than object?
Yes. Generics improve performance by avoiding unnecessary casting and boxing operations.
Should I use generics in ASP.NET Core?
Absolutely. Generics are commonly used in repositories, services, collections, and reusable application components.
Related Tutorials
- Working with Lists in C#
- C# Dictionary Examples
- LINQ Cheat Sheet
- Repository Pattern in ASP.NET Core
- Best C# Coding Practices
Conclusion
Generics are a fundamental feature of modern C# development. They help developers create reusable, type-safe, and high-performance code while reducing duplication.
By mastering generic classes, methods, collections, and constraints, you'll be able to write cleaner and more maintainable applications across ASP.NET Core, desktop applications, APIs, and libraries.