Generics in C#: Why They Are Needed and How to Use Them
\n\nWhen developing in C#, sooner or later everyone encounters a situation where the same algorithm needs to be applied to different data types. Previously, this required either writing several versions of the same method or using the object type, which led to performance loss and the risk of errors. The solution to this problem is Generics (generic types). In this article, we will break down what generics are, why they are needed, and how to use them correctly in C#.
What are Generics in C#?
\n\nGenerics are a C# language mechanism that allows you to create classes, methods, interfaces, and delegates that work with different data types without losing strong typing. Instead of writing code for each type separately, you create one universal template that substitutes the required type at compile time.
\n\nImagine you need to write a method to swap the values of two variables. Without generics, you would have to create separate methods for int, string, double, etc. With generics, you write one method that works with any type.
Here is a simple example of declaring a generic method:
\n\npublic void Swap<T>(ref T a, ref T b)\n{\n T temp = a;\n a = b;\n b = temp;\n}\n\nHere, <T> is the type parameter. The letter T is a common convention (from Type), but you can use any name. When you call the method, you specify the specific type:
int x = 5, y = 10;\nSwap<int>(ref x, ref y);\n// Now x = 10, y = 5\n\nstring first = "Hello", second = "World";\nSwap<string>(ref first, ref second);\n// Now first = "World", second = "Hello"\n\nWhy Generics are Needed: Key Benefits
\n\nUsing generics provides several important advantages that make code better and safer.
\n\n1. Type Safety
\nUnlike using object, generics check types at compile time. You cannot accidentally pass a string where a number is expected. The compiler will immediately point out the error.
2. Performance
\nWhen using object, boxing of value types (int, double, struct) into a reference type and unboxing back occurs. These are expensive operations. Generics completely eliminate these processes, as the compiler generates specialized code for each type.
3. Code Reusability
\nYou don't need to write the same algorithm for different types. One generic class or method can work with thousands of different types.
\n\n4. Readability and Maintainability
\nThe code becomes cleaner and clearer. You can explicitly see which types a method or class works with, and the logic is separated from specific data types.
\n\nHow to Use Generics: Practical Examples
\n\nLet's look at several real-world scenarios for using generics in C#.
\n\nGeneric Classes
\nThe most common example is collections. Instead of creating your own class for storing a list of numbers, strings, or custom objects, you use List<T>:
List<int> numbers = new List<int>();\nnumbers.Add(1);\nnumbers.Add(2);\n\nList<string> names = new List<string>();\nnames.Add("Alice");\nnames.Add("Bob");\n\n// Your own generic class\npublic class Repository<T>\n{\n private List<T> _items = new List<T>();\n\n public void Add(T item) => _items.Add(item);\n public T Get(int index) => _items[index];\n}\n\nRepository<int> intRepo = new Repository<int>();\nintRepo.Add(100);\nint value = intRepo.Get(0); // 100\n\nGeneric Methods
\nMethods can be generic even inside regular classes:
\n