Generics in C# allow you to write type-safe and reusable code that can work with different data types without requiring explicit casting or boxing/unboxing. They introduce the concept of type parameters, which act as placeholders for the actual types that will be specified later when the generic type is used.
You define a generic class or interface by including one or more type parameters within angle brackets <T>
after the class or interface name. For example:
public class MyGenericClass<T> {
private T myField;
public MyGenericClass(T value) {
myField = value;
}
public T GetValue() {
return myField;
}
}
In this example, T
is a type parameter. When you create an instance of `MyGenericClass`, you specify the actual type for T
:
MyGenericClass<int> intInstance = new MyGenericClass<int>(10);
MyGenericClass<string> stringInstance = new MyGenericClass<string>("hello");
Methods can also be generic. The type parameter is specified in the method signature:
public static T MyGenericMethod<T>(T arg) {
return arg;
}
You can call a generic method like this:
int result = MyGenericMethod<int>(5); // Explicitly specifying the type
string strResult = MyGenericMethod("world"); // Type inference (often preferred)
You can constrain the type parameters to specific types or interfaces using the where
keyword. This allows you to specify that a type parameter must meet certain requirements. For example:
public class MyConstrainedClass<T> where T : class, IComparable<T> { ... }
This constraint specifies that T
must be a reference type (`class`) and must implement the `IComparable<T>` interface.
Generics are a powerful feature in C# that significantly improves type safety, code reusability, and performance. They are widely used in the .NET framework and are essential for writing modern, robust C# applications.