Controla la salida en consola con precisión en C#. Aquí verás cómo añadir un parámetro opcional para decidir si mostrar evaluaciones, ordenar la lógica condicional para evitar errores y personalizar la impresión por tipo de objeto. Además, se deja lista la ruta para refactorizar múltiples if hacia switch de forma más clara.
¿Cómo controlar la impresión de evaluaciones en C#?
Para no inundar la consola, se agrega un parámetro opcional que decide si imprimir evaluaciones. Por defecto es false para reducir ruido. La clave está en el orden de las preguntas: primero se verifica el tipo y luego la intención de imprimir. Así evitamos imprimir por error cuando el flag está en false.
Usa un parámetro opcional: imprimirEvaluaciones = false.
Aplica filtrado por tipo antes del flag.
Imprime todo lo que no sea evaluación sin restricciones.
Ejemplo en C# (patrones de tipo y flujo claro):
data voidImprimirDiccionario(Dictionary<string, IEnumerable<object>> datos,bool imprimirEvaluaciones =false){foreach(var par in datos){foreach(var val in par.Value){if(val isEvaluacion eva){if(imprimirEvaluaciones) Console.WriteLine(eva.ToString());}elseif(val isEscuela esc){ Console.WriteLine($"Escuela: {esc}");}elseif(val isAlumno alu){// Solo el nombre del alumno. Console.WriteLine($"Alumno: {alu.Nombre}");}else{ Console.WriteLine(val);}}}}
¿Qué error lógico conviene evitar?
Combinar en una sola condición “quiero imprimir” y “es evaluación” puede llevar a que el bloque else imprima todo lo demás sin control. La forma segura es:
Primero: if (val es Evaluacion).
Luego: if (imprimirEvaluaciones) imprimir.
En caso contrario: imprimir siempre los demás tipos.
¿Cómo validar el resultado y depurar?
La verificación se hace con Visual Studio y la consola.
Ejecuta con dotnet run para revisar la salida.
Limpia la consola antes de reintentar si ves datos viejos.
Usa punto de interrupción y F5 para depurar paso a paso.
Observa el tipo real en tiempo de ejecución y el valor del flag.
¿Cómo personalizar la salida por tipo con if?
Se decide qué mostrar según el tipo concreto. Cuando es escuela, se imprime su ToString con etiqueta. Para alumno, solo el nombre. Para otros tipos, el valor tal cual. Este patrón organiza la lectura y facilita la depuración.
Escuela: etiqueta “Escuela:” y su ToString.
Alumno: solo el nombre.
Evaluación: respetar el flag imprimirEvaluaciones.
Manejo de condiciones con if y orden correcto de evaluación.
Llamadas a ToString para salidas legibles.
Separación de responsabilidades: flag solo afecta a evaluaciones.
¿Cómo preparar la refactorización con switch y gettype?
Cuando crecen los if anidados, es más claro migrar a switch. La idea es conmutar por el tipo del objeto para mantener casos bien separados. La transición propuesta se basa en val.GetType.
Objetivo: reemplazar múltiples if por switch.
Entrada del switch: val.GetType().
Beneficio: casos explícitos por tipo y mantenimiento sencillo.
Borrador de estructura:
switch(val.GetType()){caseType t when t ==typeof(Evaluacion):if(imprimirEvaluaciones) Console.WriteLine(val.ToString());break;caseType t when t ==typeof(Escuela): Console.WriteLine($"Escuela: {val}");break;caseType t when t ==typeof(Alumno):// Solo el nombre del alumno.var alu =(Alumno)val; Console.WriteLine($"Alumno: {alu.Nombre}");break;default: Console.WriteLine(val);break;}
¿Te gustaría ver el refactor completo a switch y comparar ambos enfoques paso a paso? Deja tu comentario con tus dudas o variantes que quieras probar.
hola Sam. Por favor cuéntanos qué problemas has tenido con el curso. Qué le hace falta para que sea más fácil de seguir?
El ejemplo se enredo tanto, que ya es difícil seguir el curso. Considero que se deben tratar cada tema con ejemplos particulares y no depender de algo gigante.
if(!(val is Evaluacion)||ImprimirEval)Console.WriteLine(val);
Ya el método completo con tu optimización.
publicvoidimprimirDiccionario(Dictionary<LlaveDiccionario,IEnumerable<ObjetoEscuelaBase>> dic, bool imprEval =false){foreach(var obj in dic){Printer.WriteTitle(obj.Key.ToString());Console.WriteLine(obj);foreach(var valor in obj.Value){if(!(valor is Evaluacion)|| imprEval)Console.WriteLine($"{obj.Key.ToString()}: {valor}");}}}
Es más sencillo así, desde mi humilde opinión:
if((impEval && val is Evaluacion)||!(val is Evaluacion))Console.WriteLine($"{obj.Key} => {val}");
Considero que la solucion es ineficiente porque entra al segundo for aunque estemos en la llave que no queremos imprimir. I checa 1 por uno el tipo del objeto.
Podemos optimizarlo con una verficacion por llave del diccionario y usando la palabra clave continue para que pase a la siguiente llave.
Ser veria algo asi.
Incluso lo podemos optimizar aun mas poniendo todo en un solo if con el operador OR.
Con esta solucion no entra al otro for y por lo tanto es mucho mas eficiente la funcion haciendo menos operaciones.
Lo hice de esta manera
publicvoidimprimirDiccionario(Dictionary<LlaveDiccionario,IEnumerable<ObjetoColegioBase>> dicc, bool eval =false){foreach(var item in dicc){Printer.EscribirTitulo(item.Key.ToString());foreach(var val in item.Value){if((val is Evaluacion&& eval)||!(val is Evaluacion)){Console.WriteLine($"{val}");}}}}
no compila eso
Aunque eso compilase, no va a funcionar, ya que en una misma condición evaluas la afirmación y la negación del objeto con un OR, por ende siempre va a dar True. =>** if(True or False) = True;**
Si separas las condiciones en IF diferentes va a andar a la perfercción.
Considero que no está mal la clase de miniproyectos que se realizan en este curso y como se abordan, pero en este caso creo que enreda demasiado, y trata de forzar el incluir conceptos en donde es complicado asimilar el ejemplo real.
Esta es la forma en que lo hice sin usar IF
foreach(var val in item.Value){var indice=val.GetType().ToString().LastIndexOf('.')+1;if(!(val is Evaluacion)|| impEvaluacion)Console.WriteLine(val.GetType().ToString().ToUpper().Substring(indice)+" : "+ val);}```
Asi me quedó.
publicvoidImprimirDiccionario(Dictionary<LLaveDiccionario,List<ObjetoEscuelaBase>> dic, bool imprEval=false){foreach(var obj in dic){Printer.WriteTitle(obj.Key.ToString());foreach(var val in obj.Value){if(imprEval ||!(val is Evaluación))//Imprime todos los objetos si imprEval es verdadero sino imprime solo no imprime Evaluaciones.System.Console.WriteLine(val);}}}```
pues yo compare si lo que querian era igual al tipo de objeto que estaba en el bucle:
publicvoidPrintDic(Dictionary<TypeOfSchoolObjets,IEnumerable<ObjetoEscuelaBase>> diccionario,TypeOfSchoolObjets tipo =TypeOfSchoolObjets.Evaluacion){var say =newList<ObjetoEscuelaBase>();foreach(var item in diccionario){ say =newList<ObjetoEscuelaBase>();if(tipo == item.Key){foreach(var obj in item.Value){ say.Add(obj);}Displays.printObjList(say,item.Key+"");}}}
Si por algún motivo no te muestra la calificación en el objeto evaluación, es porque hay que hacer override al método ToString de la clase Evaluacion para que te mueste lo que quieres.
Lo hice de esta manera
publicvoidImprimirDiccionario(Dictionary<LlaveDic,IEnumerable<ObjetoEscuelaBase>> dic,LlaveDic llaveDic){var diccionario = dic.Where(x=> x.Key is LlaveDic.Escuela);switch(llaveDic){caseLlaveDic.Cursos: diccionario = dic.Where(x=> x.Key is LlaveDic.Cursos);break;caseLlaveDic.Asignaturas: diccionario = dic.Where(x=> x.Key is LlaveDic.Asignaturas);break;caseLlaveDic.Alumnos: diccionario = dic.Where(x=> x.Key is LlaveDic.Alumnos);break;caseLlaveDic.Evaluaciones: diccionario = dic.Where(x=> x.Key is LlaveDic.Evaluaciones);break;default:break;}foreach(var k in diccionario){Console.WriteLine(k.Key.ToString());foreach(var v in k.Value){Console.WriteLine(v);}}}
publicvoidImprimirDiccionario(Dictionary<LlaveDiccionario,IEnumerable<ObjetoEscuelaBase>> dict, bool imprimirEvaluaciones =false){foreach(var obj in dict){Printer.WriteTitle($"{obj.Key}");foreach(var item in obj.Value){if(imprimirEvaluaciones || obj.Key!=LlaveDiccionario.Evaluacion)Console.WriteLine($"{item}");}}}
if(!(!imprimirEvaluaciones && val is Evaluación))
En mi caso la hice así
publicvoidImprimirDiccionario(Dictionary<LlaveDic,IEnumerable<ObjetoEscuelaBase>> dic, bool traeEvaluaciones =true, bool traeAlumnos =true, bool traeAsignaturas =true, bool traeCursos =true){foreach(var keyValPair in dic){Printer.WriteTitle(keyValPair.Key.ToString());// va a imprimir, por ejemplo Curso, Escuela, etc.foreach(var val in keyValPair.Value){// ! aca iteramos dentro de los values del diccionario, que en este caso, son ObjetosEscuelaBaseif(val is Curso&& traeCursos)// ejemplo clarisimo de downcasting{Curso cur =(Curso)val;System.Console.WriteLine($"Curso: {cur.Nombre} Alumnos: {cur.Alumnos.Count}");}if(val is Alumno&& traeAlumnos){Alumno alu =(Alumno)val; double avg =SacarPromedioAlumno(alu.Evaluaciones);System.Console.WriteLine($"Curso: {alu.Nombre} Evaluaciones: {avg}");}if(val is Asignatura&& traeAsignaturas){Asignatura mat =(Asignatura)val;System.Console.WriteLine($"Materia: {mat.Nombre}");}if(val is Evaluación&& traeEvaluaciones){Evaluación e =(Evaluación)val;System.Console.WriteLine($"Nota: {e.Nota} Materia: {e.Asignatura.Nombre}");}// si lo que quiseramos hacer es ya sea ordenar los resultados // yo agregaria cada objeto a una lista particular de cada objeto, // y despues un lindo foreach para imprimir de a listas, entones que lo que tengo // ahora quede como un "creador de listas" y hacer otra funcion que imprima las listas, // pero como no soy programador no opino.}}}
En mi caso hice la funcion de esta forma.
publicvoidImprimirDiccionario(Dictionary<LlaveDiccionario,IEnumerable<ObjetoEscuelaBase>> dic, bool imprimirEvaluaciones =false, bool imprimirCursos =false, bool imprimirAsignaturas =false, bool imprimirAlumnos =false){foreach(var obj in dic){Printer.WriteTitle(obj.Key.ToString());foreach(var value in obj.Value){if(value is Evaluacion&&!imprimirEvaluaciones)continue;if(value is Curso&&!imprimirCursos)continue;if(value is Asignatura&&!imprimirAsignaturas)continue;if(value is Alumno&&!imprimirAlumnos)continue;Console.WriteLine(value);}}}
Aunque aun muestra los carteles de titulo, estoy viendo como modificar eso.
🤯
Asi me funciona
<publicvoidImprimirDiccionario(Dictionary<LlavesDiccionario,IEnumerable<ObjetoEscuelaBase>> dic, bool imprEval =false){foreach(var obj in dic){Printer.DrawTitle(obj.Key.ToString());foreach(var valor in obj.Value){if(imprEval ==true){Console.WriteLine(valor);}else{ dic.Remove(LlavesDiccionario.Evaluaciones);Console.WriteLine(valor);}}}}>
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication1{classProgram{staticvoidMain(string[] args){ int sum =0; int numero1 =0; int numero2 =0; int numero3 =0; int numero4 =0;{Console.WriteLine("Primer Parcial"); numero1 =Int32.Parse(Console.ReadLine());}if(numero1 >15==true){Console.WriteLine("Calificacion Invalida");Console.WriteLine("Introduzca Nuevamente"); numero1 =Int32.Parse(Console.ReadLine());}{Console.WriteLine("Segundo Parcial"); numero2 =Int32.Parse(Console.ReadLine());}if(numero2 >15==true){Console.WriteLine("Calificacion Invalida");Console.WriteLine("Introduzca Nuevamente"); numero2 =Int32.Parse(Console.ReadLine());}{Console.WriteLine("Practica"); numero3 =Int32.Parse(Console.ReadLine());}if(numero3 >30==true){Console.WriteLine("Calificacion Invalida");Console.WriteLine("Introduzca Nuevamente"); numero3 =Int32.Parse(Console.ReadLine());}{Console.WriteLine("Examen Final"); numero4 =Int32.Parse(Console.ReadLine());}if(numero4 >40==true){Console.WriteLine("Calificacion Invalida");Console.WriteLine("Introduzca Nuevamente"); numero4 =Int32.Parse(Console.ReadLine());}{ sum = numero1 + numero2 + numero3 + numero4;Console.WriteLine("Su Calificacion es : {0}", sum);}if(sum <=60==true){Console.WriteLine("Reprobado ");}elseif(sum <=69==true){Console.WriteLine("Extraordinario");}elseif(sum <=95==true){Console.WriteLine("Aprobado");}elseif(sum <=100==true){Console.WriteLine("Excelente");}Console.ReadKey();}}}```
Hola buen día
tengo este problema:
Codigo:
public void ImprimirDiccionario(Dictionary<LlavesDiccionario,IEnumerable<ObjetoEscuelaBase>> dic,
bool imprEval = false)
{
foreach (var obj in dic)
{
Printer.WriteTitle(obj.Key.ToString());
//Console.WriteLine(obj);
foreach (var val in obj.Value)
{
if ( val is Evaluacion){
if (imprEval)
Console.WriteLine(val);
}
else
Console.WriteLine(val);
}
}
}
al compilar me sale este error:
Pais: Colombia, Ciudad: Bogota
| Curso |
Unhandled exception. System.InvalidCastException: Unable to cast object of type 'System.Char' to type 'CoreEscuela.Entidades.ObjetoEscuelaBase'.
at System.Linq.Enumerable.CastIteratorTResult+MoveNext()
at CoreEscuela.EscuelaEngine.ImprimirDiccionario(Dictionary`2 dic, Boolean imprEval) in D:\cursoPlatzi\platzi\CoreEscuela\App\EscuelaEngine.cs:line 67
at CoreEscuela.Program.Main(String[] args) in D:\cursoPlatzi\platzi\CoreEscuela\Program.cs:line 50
PS D:\cursoPlatzi\platzi\CoreEscuela>
Hola, aquí mi implementación: Si valor es de tipo Evaluación y printEvaluacion es falso, hago que el ciclo se continúe con el siguiente valor con la palabra reservada continue. En caso contrario, que imprima el valor llano y plano, anexo código:
publicvoidImprimirDiccionario(Dictionary<LlaveDiccionario,IEnumerable<ObjetoEscuelaBase>> dicc, bool printEval =false){foreach(var obj in dicc){Printer.WriteTitle( obj.Key.ToString());foreach(var val in obj.Value){if( val is Evaluacion&&!printEval ){continue;}else{Console.WriteLine( val );}}}}