Diccionarios con polimorfismo en C#

Clase 16 de 35Curso de C# con .Net Core 2.1

Resumen

Implementa un diccionario robusto en C# para organizar tu modelo escolar con claves de tipo string y colecciones tipadas. Aquí verás cómo evitar excepciones por llaves duplicadas, cómo aprovechar el polimorfismo y por qué conviene devolver una interfaz como IEnumerable en lugar de una List concreta. Todo, paso a paso, desde Visual Studio.

¿Qué construimos con un diccionario string a objetos en C#?

Un método que devuelva un Dictionary>. La clave es un string (por ejemplo, "escuela" o "cursos") y el valor es una colección de ObjetoEscuelaBase. Esta decisión permite indexar los distintos tipos del dominio escolar con una sola estructura.

  • Claves legibles: "escuela", "cursos".
  • Valores consistentes: siempre una colección de ObjetoEscuelaBase.
  • Método claro: get diccionario de objetos.

Ejemplo en C#:

public Dictionary<string, IEnumerable<ObjetoEscuelaBase>> GetDiccionarioDeObjetos()
{
    var diccionario = new Dictionary<string, IEnumerable<ObjetoEscuelaBase>>();

    // escuela: un único objeto envuelto en colección.
    diccionario.Add("escuela", new ObjetoEscuelaBase[] { escuela });

    // cursos: conversión explícita a la jerarquía base.
    IEnumerable<ObjetoEscuelaBase> cursosComoBase = cursos.Cast<ObjetoEscuelaBase>();
    diccionario.Add("cursos", cursosComoBase);

    return diccionario;
}

¿Cómo evitamos colisiones de llave y valores incompatibles?

Agregar varias veces la misma clave (por ejemplo, "cursos") provoca una excepción por llave duplicada. La solución no es inventar claves como "curso2" o "curso3", sino usar una sola clave y entregar todos los cursos como colección.

  • Un valor por clave: evita repetir "cursos" para cada curso.
  • Colección única: agrupa todos los cursos debajo de "cursos".
  • Envoltura mínima: para "escuela", usa un array de una posición.

Fragmento clave:

// Escuela como colección (array de 1 elemento).
diccionario.Add("escuela", new ObjetoEscuelaBase[] { escuela });

// Todos los cursos en una sola entrada.
diccionario.Add("cursos", cursos.Cast<ObjetoEscuelaBase>());

¿Por qué usar IEnumerable y hacer casting con polimorfismo?

Aunque un curso hereda de ObjetoEscuelaBase, una List no es una List. No existe conversión implícita ni explícita entre listas genéricas de tipos distintos. Por eso, cuando trabajas con colecciones derivadas, C# exige conversión a una interfaz común.

  • Polimorfismo: Curso es compatible con ObjetoEscuelaBase.
  • Colecciones genéricas: List de derivados no hereda de List de base.
  • Interfaz genérica: usa IEnumerable en el diccionario.
  • Conversión clara: aplica .Cast() a la colección de cursos.

Código ilustrativo:

// List<Curso> cursos;  // colección concreta
// Convertimos al tipo base, como interfaz (no como List).
IEnumerable<ObjetoEscuelaBase> cursosComoBase = cursos.Cast<ObjetoEscuelaBase>();

// El diccionario expone IEnumerable, compatible con el resultado de Cast.
var diccionario = new Dictionary<string, IEnumerable<ObjetoEscuelaBase>>
{
    { "escuela", new ObjetoEscuelaBase[] { escuela } },
    { "cursos",  cursosComoBase }
};

Puntos clave del diseño:

  • Exponer interfaces: IEnumerable ofrece flexibilidad y encaja con .Cast<>.
  • Evitar casting inválido: no intentes convertir List a List.
  • Uniformidad: el valor del diccionario siempre es colección, incluso para un único elemento.

¿Qué habilidades y conceptos practicas aquí?

  • Diseño de API: firmas claras que devuelven interfaces.
  • Estructuras de datos: Dictionary con clave string y valor colección tipada.
  • Polimorfismo práctico: derivados convertidos a la clase base.
  • Conversión explícita: uso de .Cast<> con colecciones.
  • Manejo de errores: prevención de excepción por llave duplicada.

¿Te gustaría ver variantes con otras colecciones o claves adicionales del dominio? Cuéntame en comentarios qué caso quieres mapear y lo construimos juntos.

      Diccionarios con polimorfismo en C#