Genéricos en C# (List<T>, Dictionary<TKey,TValue>)
Aprende genéricos en C# (List<T>, Dictionary<TKey,TValue>) para escribir código reutilizable y seguro de tipos con ejemplos.
En C#, los genéricos se utilizan para aumentar la seguridad de tipos y la flexibilidad. Las clases y colecciones genéricas eliminan la necesidad de conversiones de tipo en tiempo de ejecución y evitan operaciones innecesarias de boxing y unboxing, mejorando el rendimiento y reduciendo el riesgo de errores. Antes de la introducción de los genéricos, colecciones como ArrayList almacenaban sus elementos como object. Cuando un tipo de valor como int se agregaba a un ArrayList, debía convertirse (boxing) a object y luego volver a su tipo original (unboxing) al recuperarlo. Este proceso generaba asignaciones adicionales de memoria y un impacto negativo en el rendimiento. Con colecciones genéricas como List<T> y Dictionary<TKey,TValue>, los elementos se almacenan en su tipo real, eliminando estos costos y haciendo que el código sea más seguro y más eficiente.
List<T>
List<T> es una colección genérica que almacena dinámicamente elementos de un tipo específico.
T define el tipo de elementos que contendrá la lista.
using System;
using System.Collections.Generic;
var numeros = new List<int>();
numeros.Add(10);
numeros.Add(20);
numeros.Add(30);
foreach (int n in numeros)
Console.WriteLine(n);
// Salida:
// 10
// 20
// 30
Nota: A diferencia de los arreglos, List<T> puede crecer y reducirse dinámicamente.
Dictionary<TKey,TValue>
Dictionary es una colección genérica de pares clave–valor.
TKey define el tipo de la clave, y TValue define el tipo del valor.
using System;
using System.Collections.Generic;
var estudiantes = new Dictionary<int, string>();
estudiantes[101] = "Juan";
estudiantes[102] = "María";
estudiantes[103] = "Miguel";
foreach (var kv in estudiantes)
Console.WriteLine($"{kv.Key} → {kv.Value}");
// Salida:
// 101 → Juan
// 102 → María
// 103 → Miguel
Nota: Cada Key en un diccionario debe ser único.
Intentar agregar una clave existente provocará un error.
Crear tus propias clases genéricas
No solo puedes usar las colecciones integradas, también puedes definir tus propios tipos genéricos. Esto permite crear estructuras reutilizables y seguras en cuanto a tipos.
public class Caja<T>
{
public T Valor { get; set; }
public void Imprimir()
{
Console.WriteLine($"La caja contiene: {Valor}");
}
}
class Program
{
static void Main()
{
var intCaja = new Caja<int> { Valor = 42 };
intCaja.Imprimir();
var stringCaja = new Caja<string> { Valor = "Hola" };
stringCaja.Imprimir();
}
}
// Salida:
// La caja contiene: 42
// La caja contiene: Hola
Restricciones genéricas (Constraints)
Los tipos genéricos pueden usar restricciones (con la palabra clave where)
para imponer ciertos requisitos a los parámetros de tipo.
public class Repositorio<T> where T : class
{
private readonly List<T> _items = new();
public void Agregar(T item) => _items.Add(item);
public void ImprimirTodos()
{
foreach (var i in _items)
Console.WriteLine(i);
}
}
class Program
{
static void Main()
{
var repo = new Repositorio<string>();
repo.Agregar("Bolígrafo");
repo.Agregar("Cuaderno");
repo.ImprimirTodos();
}
}
// Salida:
// Bolígrafo
// Cuaderno
Aplicación de ejemplo: Gestión de productos
En el siguiente ejemplo, la información de los productos se almacena en una List<Product>,
y las asociaciones ID–nombre de los productos se guardan en un Dictionary<int,string>.
public class Producto
{
public int Id { get; set; }
public string Nombre { get; set; } = string.Empty;
}
class Program
{
static void Main()
{
var productos = new List<Producto>
{
new Producto { Id = 1, Nombre = "Portátil" },
new Producto { Id = 2, Nombre = "Teléfono" }
};
var diccionarioProductos = new Dictionary<int, string>();
foreach (var p in productos)
diccionarioProductos[p.Id] = p.Nombre;
Console.WriteLine("Productos:");
foreach (var kv in diccionarioProductos)
Console.WriteLine($"{kv.Key} - {kv.Value}");
}
}
// Salida:
// Productos:
// 1 - Portátil
// 2 - Teléfono
Alternativa con LINQ: También puede convertir la lista directamente en un diccionario utilizando ToDictionary.
var diccionarioProductos = productos.ToDictionary(p => p.Id, p => p.Nombre);
Console.WriteLine("Productos:");
foreach (var kv in diccionarioProductos)
Console.WriteLine($"{kv.Key} - {kv.Value}");
Resumen (TL;DR)
- Los genéricos mejoran la seguridad de tipos y la reutilización.
List<T>: Lista dinámica y segura en tipos.Dictionary<TKey,TValue>: Búsqueda rápida con claves únicas.- Puedes crear tus propias clases genéricas y aplicar restricciones de tipo.
- Los genéricos son eficientes y reducen la necesidad de boxing/unboxing.
Artículos relacionados
Arreglos (Arrays) en C#
Aprende arreglos en C#: declaración, índices, recorridos con bucles y operaciones básicas con ejemplos prácticos.
Colecciones en C#: Lista, Diccionario, Cola, Pila
Aprende colecciones en C# como List, Dictionary, Queue y Stack para gestionar datos de forma eficiente con ejemplos.
Conversiones de tipos en C#
Aprende las conversiones de tipos en C#, incluyendo casting implícito y explícito, Parse, TryParse y métodos Convert con ejemplos.