Generics en C#: guía completa sobre uso y ventajas

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Generics en C#: para qué sirven y cómo usarlos



Los tipos genéricos (Generics) son una de las características clave del lenguaje C# que permite crear clases, métodos e interfaces con tipos parametrizados. En lugar de escribir el mismo código para cada tipo de dato, lo escribes una vez y especificas el tipo al usarlo. Esto mejora el rendimiento, la seguridad de tipos y la reutilización del código. En este artículo analizaremos para qué sirven los Generics, cómo aplicarlos en la práctica y veremos ejemplos reales de .NET.



Para qué sirven los Generics en C#



Antes de la aparición de los Generics en C# (versión 2.0), los desarrolladores solían usar el tipo object y las colecciones ArrayList. Esto provocaba dos problemas:



  • Pérdida de rendimiento — boxing y unboxing para tipos por valor (int, double, struct).
  • Falta de verificación de tipos en tiempo de compilación — se podía accidentalmente poner una cadena en una lista de números y obtener un error solo en tiempo de ejecución.


Los Generics resuelven ambos problemas. Permiten crear estructuras de datos type-safe sin sobrecargas innecesarias. Por ejemplo, List<int> trabaja con int sin boxing, y el compilador no permitirá agregar una cadena allí.



Conceptos básicos de Generics



Clases genéricas



Una clase genérica se declara con un parámetro de tipo entre corchetes angulares. El parámetro de tipo es un placeholder que se reemplaza por el tipo real al crear una instancia.



public class Box<T>{    private T _value;

public Box(T value) { _value = value; }

public T GetValue() => _value;}


Uso:



var intBox = new Box<int>(42);var stringBox = new Box<string>("Hello");

Console.WriteLine(intBox.GetValue()); // 42Console.WriteLine(stringBox.GetValue());// Hello


Métodos genéricos



Un método puede tener su propio parámetro de tipo, incluso si la clase no es genérica:



public class Utils{    public static void Swap<T>(ref T a, ref T b)    {        T temp = a;        a = b;        b = temp;    }}

// Usoint x = 1, y = 2;Utils.Swap(ref x, ref y);Console.WriteLine($"{x} {y}"); // 2 1


Interfaces genéricas



Las interfaces con parámetro de tipo permiten crear abstracciones flexibles:



public interface IRepository<T>{    T GetById(int id);    void Add(T entity);}

public class UserRepository : IRepository<User>{ public User GetById(int id) => new User(); public void Add(User user) { }}


Restricciones (Constraints) en Generics



A veces es necesario imponer restricciones sobre los tipos que pueden ser utilizados. Para esto se usa la palabra clave where.



Tipos principales de restricciones



  • where T : class — solo tipos por referencia (string, clases).
  • where T : struct — solo tipos por valor (int, DateTime, struct).
  • where T : new() — el tipo debe tener un constructor público sin parámetros.
  • where T : SomeBaseClass — el tipo debe ser o heredar de la clase especificada.
  • where T : ISomeInterface — el tipo debe implementar la interfaz.


Ejemplo con múltiples restricciones:



public class Repository<T> where T : class, IEntity, new(){    public T Create()    {        return new T(); // permitido gracias a new()    }}


Covarianza y Contravarianza en Generics



A partir de C# 4.0, se agregó la posibilidad de gestionar la varianza de interfaces genéricas mediante las palabras clave in y out.



  • Covarianza (out) — permite usar

Blogs

Book Recommendations