Generics y tipificación en C#: escribiendo código flexible sin copiar y pegar

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 y tipificación en C#: ¿por qué no puedes prescindir de ellos?



Imagina que estás construyendo una casa, pero cada vez que necesitas clavar un clavo, tallas un martillo nuevo específicamente para ese clavo. ¿Absurdo? Así es exactamente el código sin generalizaciones (Generics). En C#, los Generics son ese martillo universal que sirve para cualquier tarea, pero sin perder precisión.



Hoy analizaremos cómo los Generics y la tipificación en C# transforman tu código de un conjunto de parches inconexos en un sistema ordenado, flexible y seguro. Aprenderás a escribir métodos y clases universales que funcionan con cualquier tipo de dato, sin sacrificar el rendimiento. ¡Allá vamos!



¿Qué son los Generics y para qué sirven?



Los Generics (generalizaciones) son un mecanismo que permite crear clases, métodos e interfaces que funcionan con cualquier tipo de dato, pero manteniendo una tipificación estricta en tiempo de compilación. ¿Suena complicado? En realidad es sencillo.



Antes de la llegada de los Generics en C# (versión 2.0, 2005), los desarrolladores usaban dos enfoques:

  • Copiar y pegar — crear una clase separada para cada tipo (int, string, double, etc.).
  • object — usar el tipo base object, lo que provocaba boxing/unboxing y pérdida de rendimiento.


Ambas opciones son malas. La primera consume tiempo, la segunda consume rendimiento. Los Generics resuelven ambos problemas a la vez.



¿Cómo se ve un Generic en la práctica?



// Sin Generics: copiar y pegar para cada tipopublic class IntList{    private int[] items = new int[10];    public void Add(int item) { /* ... */ }}

public class StringList{ private string[] items = new string[10]; public void Add(string item) { /* ... */ }}

// Con Generics: una clase para todos los casospublic class GenericList<T>{ private T[] items = new T[10]; public void Add(T item) { /* ... */ }}

// Usovar intList = new GenericList<int>();var stringList = new GenericList<string>();


Observa: GenericList<T> es una plantilla. En lugar de T, colocas cualquier tipo (int, string, tu propia clase), y el compilador crea una versión específica del código para ese tipo. Sin duplicación, sin object.



Tipificación en C#: estática, estricta, segura



Antes de profundizar, recordemos que C# es un lenguaje con tipificación estática. Esto significa que el tipo de cada variable se determina en tiempo de compilación. Los Generics no rompen esta regla, al contrario, la refuerzan.



Cuando escribes List<int>, el compilador sabe exactamente que dentro de la lista solo hay números enteros. Si intentas agregar una cadena, obtendrás un error de compilación, no una excepción en tiempo de ejecución. Esto es la seguridad de tipos.



Generics vs object: batalla de rendimiento



// Mal ejemplo con objectArrayList badList = new ArrayList();badList.Add(123);           // Boxing int -> objectint value = (int)badList[0]; // Unboxing object -> int

// Buen ejemplo con GenericsList<int> goodList = new List<int>();goodList.Add(123); // Sin boxingint value = goodList[0]; // Sin unboxing


Para tipos de valor (int, double, struct), la diferencia de rendimiento puede ser de 10 a 20 veces. Para tipos de referencia (class), no hay boxing, pero los Generics siguen ganando al evitar conversiones de tipo.



Métodos universales: flexibilidad sin código extra



Los Generics no solo funcionan con clases, sino también con métodos. Supongamos que necesitas escribir un método que intercambie dos elementos. Sin Generics, tendrías que escribir muchas sobrecargas:



// Sin Genericspublic void SwapInt(ref int a, ref int b) { int temp = a; a = b; b = temp; }public void SwapString(ref string a, ref string b) { string temp                

Blogs

Book Recommendations