Generics in C#
Generics allow us to create classes, methods, interfaces, and collections that can work with different data types while providing type safety.
Why Do We Use Generics?
Without generics, we may need to create separate classes or methods for different data types. Generics help us write one reusable implementation.
- Provides type safety.
- Reduces duplicate code.
- Improves code reusability.
- Provides better compile-time checking.
- Works efficiently with .NET collections.
- Makes applications easier to maintain.
Generic Syntax
class ClassName<T>
{
// Class members
}
Here, T represents a type parameter. It can represent different data types such as int, string, double, or custom classes.
Generic Class
A generic class allows us to create a class that can work with different data types.
using System;
class Box<T>
{
public T Value { get; set; }
}
class Program
{
static void Main()
{
Box<int> numberBox = new Box<int>();
numberBox.Value = 100;
Console.WriteLine(numberBox.Value);
}
}
Output
100
Generic Class with Different Data Types
The same generic class can be used with different data types.
using System;
class Box<T>
{
public T Value { get; set; }
}
class Program
{
static void Main()
{
Box<int> numberBox = new Box<int>();
numberBox.Value = 100;
Box<string> textBox = new Box<string>();
textBox.Value = "CIIT";
Console.WriteLine(numberBox.Value);
Console.WriteLine(textBox.Value);
}
}
Output
100
CIIT
Generic Method
A generic method can work with different data types without creating separate methods for each type.
using System;
class Program
{
static void Display<T>(T value)
{
Console.WriteLine(value);
}
static void Main()
{
Display<int>(100);
Display<string>("Hello");
}
}
Output
100
Hello
Generic Method Type Inference
C# can often determine the generic type automatically from the value passed to the method.
using System;
static void Display<T>(T value)
{
Console.WriteLine(value);
}
Display(100);
Display("CIIT");
Display(25.5);
Output
100
CIIT
25.5
Generic List
One of the most common examples of generics in C# is List<T>. The type inside < > specifies what type of data the list can store.
using System;
List<int> numbers = new List<int>();
numbers.Add(10);
numbers.Add(20);
numbers.Add(30);
foreach (int number in numbers)
{
Console.WriteLine(number);
}
Output
10
20
30
Generic List with String
using System;
List<string> students = new List<string>();
students.Add("Rahul");
students.Add("Sneha");
students.Add("Amit");
foreach (string student in students)
{
Console.WriteLine(student);
}
Output
Rahul
Sneha
Amit
Generic Dictionary
Dictionary<TKey, TValue> is another commonly used generic collection. It stores data in key-value pairs.
using System;
Dictionary<int, string> students =
new Dictionary<int, string>();
students.Add(101, "Rahul");
students.Add(102, "Sneha");
students.Add(103, "Amit");
Console.WriteLine(students[102]);
Output
Sneha
Generic Interface
Interfaces can also use generic type parameters. This allows an interface to work with different types.
using System;
class Storage<T> where T : class
{
public T Value { get; set; }
}
class Student
{
public string Name { get; set; }
}
class Program
{
static void Main()
{
Storage<Student> storage = new Storage<Student>();
storage.Value = new Student
{
Name = "Rahul"
};
Console.WriteLine(storage.Value.Name);
}
}
Output
Student Added: Rahul
Generic Constraints
Generic constraints allow us to restrict the types that can be used with a generic class or method.
For example, the where T : class constraint specifies that T must be a reference type.
using System;
class Storage<T> where T : class
{
public T Value { get; set; }
}
class Student
{
public string Name { get; set; }
}
class Program
{
static void Main()
{
Storage<Student> storage = new Storage<Student>();
storage.Value = new Student
{
Name = "Rahul"
};
Console.WriteLine(storage.Value.Name);
}
}
Output
Rahul
Type Safety with Generics
Generics provide compile-time type checking. This helps prevent invalid data from being added to a strongly typed collection.
using System;
List<int> numbers = new List<int>();
numbers.Add(10);
numbers.Add(20);
// numbers.Add("Hello"); // Compile-time error
Generics vs Non-Generic Collections
| Feature | Generics | Non-Generic |
|---|---|---|
| Type Safety | Strong type safety | Less type safety |
| Performance | Generally better | May require casting |
| Code Reusability | High | Lower |
| Common Example | List<T> | ArrayList |
Common Generic Types in .NET
| Generic Type | Purpose |
|---|---|
| List<T> | Stores a dynamic list of strongly typed elements |
| Dictionary<TKey,TValue> | Stores key-value pairs |
| HashSet<T> | Stores unique elements |
| Queue<T> | Stores elements using FIFO behavior |
| Stack<T> | Stores elements using LIFO behavior |
Example 👨🏫🌍
Generics are widely used in real-world .NET applications. For example, an application may use a generic repository to work with different database entities.
using System;
List<string> courses = new List<string>();
courses.Add("C#");
courses.Add(".NET");
courses.Add("ASP.NET Core");
foreach (string course in courses)
{
Console.WriteLine(course);
}
Output
C#
.NET
ASP.NET Core
Common Mistakes with Generics
- Use the correct generic type for your data.
- Do not try to add incompatible data types to strongly typed collections.
- Understand the difference between TKey and TValue in Dictionary.
- Use generic constraints when a type needs specific requirements.
- Prefer generic collections for strongly typed application code.
Interview Questions
1. What are Generics in C#?
Generics allow developers to create reusable and type-safe classes, methods, interfaces and collections.
2. What is the advantage of Generics?
Generics provide type safety, code reusability and better maintainability.
3. What is T in Generics?
T is a type parameter that represents a data type.
4. What is a generic class?
A generic class is a class that can work with different data types using a type parameter.
5. What is a generic method?
A generic method is a method that can work with different data types using a type parameter.
6. What is a generic constraint?
A generic constraint restricts the types that can be used as a generic type parameter.
Generics Summary
- Generics allow reusable and type-safe code.
- Generic classes can work with different data types.
- Generic methods can work with different data types.
- List<T> is a commonly used generic collection.
- Dictionary<TKey,TValue> stores key-value pairs.
- Generic constraints restrict valid type parameters.
- Generics improve code reusability and maintainability.
- Generics are widely used in modern .NET applications.
Practice Questions
- Create a generic class that stores an integer value.
- Create a generic class that stores a string value.
- Create a generic method to display different data types.
- Create a List<int> and add five numbers.
- Create a List<string> and add five student names.
- Create a Dictionary<int,string> for student records.
- Create a generic class with a class constraint.
- Explain the difference between generic and non-generic collections.
- Explain the advantages of Generics in C#.
- Create a generic repository-style class example.