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<string, IEnumerable<ObjetoEscuelaBase>>. 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#:
publicDictionary<string, IEnumerable<ObjetoEscuelaBase>>GetDiccionarioDeObjetos(){var diccionario =newDictionary<string, IEnumerable<ObjetoEscuelaBase>>();// escuela: un único objeto envuelto en colección. diccionario.Add("escuela",newObjetoEscuelaBase[]{ 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",newObjetoEscuelaBase[]{ 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<Curso> no es una List<ObjetoEscuelaBase>. 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<ObjetoEscuelaBase> en el diccionario.
Conversión clara: aplica .Cast<ObjetoEscuelaBase>() 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 =newDictionary<string, IEnumerable<ObjetoEscuelaBase>>{{"escuela",newObjetoEscuelaBase[]{ 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<Curso> a List<ObjetoEscuelaBase>.
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.
... De hecho en la colección de Cursos dentro del .Add() que invocamos del diccionario NO es necesario invocarlo. La razón de esto es porque no necesita su invocación debido a que Cursos es de un tipo "List<Curso>", la cual implementa la interfaz "IEnumerable<T>". De hecho al invocar al método .Add() de nuestro diccionario se me ocurrió añadir dentro del "Value" una lista de ObjetoEscuelaBase inicializada con un elemento, que es nuestra Escuela. De tal forma que el código me quedó de esta forma sin que el compilador me protestara por hacerlo así:
Entiendo que el uso del Método Cast() en las colecciones sirve precisamente para convertir CADA ELEMENTO CONTENIDO de un tipo a otro.
Esto lo pueden corroborar en el libro titulado: "Training Kit - 70-516 Accessing Data With Microsoft .Net Framework 4", Editorial Microsoft Press, pagina167, chapter 3: Undestanding Linq.
Siento que esta clase es bastante avanzada, hay que poner mucha atención y recordar lo que se hizo antes al aprender polimorfismo y cast para entenderla bien. :O
Bastante confusa esta clase, no entendi
Que no entiendes Juan? podrias empezar por lo mas simple
Cada registro del diccionario va a devolver un string y una colección de objetos
Tal vez es un mal ejemplo.
Se está implementando un método que tiene demasiadas responsabilidades: devolver muchas cosas al mismo tiempo. Se ve muy forzado devolver la escuela en un array de 1, etc. Pienso que rompe principios de orientación a objetos (SOLID).
Tienes razón, ya se esta enredando mucho con estos ejemplos.
por alguna razon, no necesité hacerle cast, aceptó los cursos como tal.
var dictionary =newDictionary<string,IEnumerable<Inheritor>>{}; dictionary.Add("Escuela",new[]{schoolCopy1}); dictionary.Add("Course", schoolCopy1.schoolCourses);var debugPoint =0;
Igualmente
No entiendo por que el "casteo" a escuela.cursos, si se supone que escuela.cursos es una lista de cursos, que hereda de objetosEscuelaBase
Si, un detalle que se le pasó porque no hay necesidad.
Teniendo en cuenta:
Dictionary<key, value> dictionary = new Dictionary<key, value>();
Al agregar un valor se puede realizar de las siguientes dos maneras:
1- dictionary.Add("key", "value");
ó
2- dictionary["key"] = "value";
La primer opción agrega, siendo que la segunda opción iguala, por lo que si se utiliza mas de dos veces la segunda opción en la primera lo agregará, pero en la segunda lo igualará o reemplazará. Mientras que en la primera opción la primera vez lo agregará, pero en la segunda ocasión marcara una excepción porque la llave ya estaba en el diccionario.
Que buena observación!
haciendo casting a los objetos jjajjaja
Esta clase la considero un claro ejemplo del uso de listas polimórficas, que conociendo la estructura u herencia de los objetos puedes hacer tantas combinaciones y/o recorridos de tus objetos como necesites.
Supongo que el concepto es intentar hacer una especie de JSON-Singleton con los datos de la escuela para consulta indexada, ¿no?
Como seria la serializacion de un dictionario json en core
Ejemplo de json
{
“arrayColores”:[{
“nombreColor”:“rojo”,
“valorHexadec”:"#f00"
},
{
“nombreColor”:“verde”,
“valorHexadec”:"#0f0"
},
{
“nombreColor”:“azul”,
“valorHexadec”:"#00f"
},
{
“nombreColor”:“cyan”,
“valorHexadec”:"#0ff"
},
{
“nombreColor”:“magenta”,
“valorHexadec”:"#f0f"
},
{
“nombreColor”:“amarillo”,
“valorHexadec”:"#ff0"
},
{
“nombreColor”:“negro”,
“valorHexadec”:"#000"
}
]
}
No entendí nadita.
Para que voy a usar el cast()?
.Cursos es una lista de curso, una lista es una ienumerable, asi que IEnumerable lo va a aceptar, y curso hereda de ObjetoEscuelaBase por lo que, que un IEnumerable<ObjetoEscuelaBase> sea igual a una lista<curso> no me va a generar ningun problema, no tengo que cambiar su tipo.
No me queda claro al final cuando es que deberia usarlo?
Se que es un metodo de los IEnumerable que convierte los objetos dentro de una secuencia a otro tipo de objeto, como en un list de objetos A pasa a ser el mismo list de objetos B.
Ahhhhh! Que me enredé! Ayuda programadores
El profesor almacena un curso, por eso lo debe adicionar en un arreglo. Para cumplir la condicción del diccionario.
@JimmyBuritica Gracias.
No se entiende muy bien la explicaciòn, creo que es muy confuso.
En que parte no entendiste?
Esta clase tiene un pequeño error, cuando cambia del tipo List a IEnumerable solo cambió el tipo del método y no cambió el tipo del valor de retorno, y eso le causó los problemas de casteo.
Con esta linea se arregla todo:
var diccionario = new Dictionary<string, List<ObjetoEscuelaBase>>();
Alguien me podría decir en que clase explica un error que se genera en código de bajo nivel, donde un aconversion explicita hace que el codigo ensamblador lo maneja con un stack y hace que trabaje mas. Algo asi no recuerdo muy bien.
Aqui está el código si se quiere que retorne un diccionario de tipo