Crear consultas claras y reportes útiles en C sharp es más sencillo cuando estructuramos bien los datos y aplicamos validaciones sólidas. Aquí construimos un reporteador que usa un diccionario indexado por una enumeración, maneja excepciones de forma explícita y expone resultados como IEnumerable para mantener el encapsulamiento.
¿Cómo diseñar el reporteador en C sharp para consultas y reportes?
El objetivo es centralizar las consultas en una clase llamada Reporteador, dentro del namespace correcto (por ejemplo, CoreEscuela.App). La decisión clave: recibir en el constructor un diccionario cuyas llaves son una enumeración (las entidades) y cuyos valores son listas de objetos de la escuela. Así, el reporteador puede generar reportes reutilizables a partir de datos ya construidos.
Clase de orquestación: agrupa lógica de consultas y reportes.
Entrada única: un diccionario indexado por enum con listas de objetos.
Menos acoplamiento: el reporteador no crea datos, solo los consulta.
¿Qué rol cumple el diccionario con enumeración como llave?
El diccionario concentra “todo” lo que la aplicación generó: cursos, alumnos, evaluaciones, etc., indexado por una enumeración. La búsqueda es directa: se consulta la llave correspondiente a Evaluación y se obtiene su lista. Esto separa el “dónde están los datos” del “cómo los uso” y habilita reportes consistentes.
Llave: una enumeración que representa la entidad (p. ej., Evaluación).
Valor: lista de objetos de esa entidad.
Beneficio: acceso rápido y tipado firme.
¿Por qué el constructor valida nulos con ArgumentNullException y nameof?
Para evitar errores silenciosos, si el diccionario llega nulo, el constructor falla con throw new ArgumentNullException(nameof(diccionario)). Así se detiene la ejecución temprano y el mensaje es claro.
Uso de throw explícito.
Excepción específica: ArgumentNullException en lugar de la genérica.
Por convención, los campos privados inician con underscore. Esto facilita lectura y mantenimiento. Además, es clave ubicar la clase en el namespace correcto según la carpeta del proyecto para evitar errores de referencia.
Campo privado: _diccionario.
Namespace consistente con la estructura del proyecto.
Constructor con nivel de protección público para poder instanciar.
Instanciación típica desde el programa:
var reporteador =newReporteador(engine.GetDiccionarioDeObjetos());
¿Qué debes saber de clases estáticas y constructores estáticos en C sharp?
Se intentó hacer el reporteador como clase estática, pero se descartó para no complicar. Aun así, quedaron reglas importantes.
Una clase estática requiere constructor estático.
El constructor estático no admite parámetros y no lleva modificadores de acceso.
Útil para inicializaciones globales, pero innecesario si se requiere inyección de dependencias o parámetros.
Sin modificadores de acceso: el lenguaje lo impone.
Se ejecuta una vez, antes del primer uso del tipo.
¿Cuándo evitar una clase estática para simplificar?
Cuando necesitas recibir dependencias por constructor (como el diccionario) o probar con diferentes entradas, una clase no estática es más flexible. Así mantienes el código claro y evitas límites innecesarios.
¿Cómo exponer evaluaciones con IEnumerable sin romper el encapsulamiento?
Al exponer colecciones hacia el exterior, es buena práctica retornar IEnumerable o una lista de solo lectura. Así comunicas “esto se recorre, no se modifica” y proteges el estado interno.
Contrato mínimo: IEnumerable para iterar.
Evita mutaciones no controladas.
Facilita pruebas y composición de consultas.
Implementación de la consulta de evaluaciones:
publicIEnumerable<Evaluacion>GetListaDeEvaluaciones(){// Asume que la llave TipoEntidad.Evaluacion existe y está cargada.return(IEnumerable<Evaluacion>) _diccionario[TipoEntidad.Evaluacion];}
Y al usar el diccionario, procede con cautela: si la llave no existe o la colección no se cargó, se lanzará una excepción. Por eso es recomendable validar antes de acceder directamente cuando no controlas todo el flujo de carga.
Verifica la existencia de la llave antes de acceder.
Evita suposiciones sobre el estado de carga.
Maneja errores de forma explícita para diagnósticos claros.
¿Te gustaría que agreguemos filtros por curso, alumno o rangos de fechas en los reportes? Cuéntame qué necesitas y seguimos construyendo juntos.
Aportando a lo inicial del curso referente al por qué los constructores de las clases estáticas NO llevan parámetros es porque estas no pueden ser instanciadas, es decir, no podemos crear objetos a partir de ellas, además están selladas y no pueden heredarse.
Siguiendo, una clase NO estática puede contener un constructor estático sí y sólo sí tiene miembros estáticos (métodos, propiedades, eventos) pero este constructor, como todo constructor estático, se ejecuta una sóla vez y será el primero en ejecutarse antes que cualquier otro constructor no estático.
Espero les sirva, saludos.
Excelente explicación compañero.
Gracias!
Los constructores estáticos solo se ejecutan una sola vez cuando se crea la primera instancia, aunque se realicen múltiples instancias este constructor ya no vuelve a ser llamado.
No soy muy apegado a los IDEs pero dada la complejidad natural del software pues hago uso de ellos.
Para todos aquellos que quieren comenzar a programar con C# y .Net y necesiten o desean probar alternativas profesionales a Visual Studio y/o VSC, recomiendo:
Rider by JetBrains
Chulada de IDE, muy profesional, cuesta pero si estudian pueden ganarse una beca con github student pack y les dan licencias para las versiones PRO de la mayoría de los software de JetBrains.
Todo su software es de nivel.
Datos brain breaker: Los productos de JetBrains están programados en Java, la empresa es de Republica Checa y he notado como compila las soluciones a mayor velocidad que Eclipse o Visual Studio Community.
JetBrains ofrece la versión profresional para estudiantes universitarios. Siempre y cuando estudien, ya que debes crear la cuenta con el tu mail de la universidad.
Sobre los constructores static:
Si se desea utilizar un constructor estático dentro de una clase no estática, permite la inicialización de cualquier dato y realiza acciones particulares llamándose de forma automática antes de crear la primera instancia, se puede utilizar para:
Cuando la clase usa archivos de registro y el constructor se usa para escribir entradas en este archivo.
Para crear clases con código no administrado.
Para verificar tipo de parámetros en tiempo de ejecución los cuales no pueden ser verificados en tiempo de compilación.
Solo como aclaración, los constructores en C# no se heredan de la super clase:
Inheritance in C# and .NET · Background: What is inheritance?
Se usa el base() si no me equivoco
Efectivamente puedes llamar al constructor de la super-clase usando la sintaxis :base como en el siguiente ejemplo:
public class MyClass : MyParentClass
{
public MyClass(int param1) : base() { }
}
Sin embargo, el constructor no se hereda nunca; cada clase tiene sus propios constructores y hay que llamar al adecuado mediante la sintaxis anterior.
Existe una excepción a esto y es que si no se indica nada y se tiene un constructor predeterminado, la creación de la subclase, invoca al constructor predeterminado de su super-clase sin hacer nada más, pero aun así, cada constructor sigue estando declarado en su propia clase y no es accesible en la interfaz pública de la subclase a menos que se declare puntualmente: es decir, incluso en este caso, los constructores nunca se heredan.
En este caso
<static curso {}>
lo que sucede es que se inicia liza una solo vez cuando se llama la clase, es algo parecido en java
<publicclassprueba{static{System.out.println("Pueba de codigo");}}>
minuto 0:33 El profesor dio clic derecho y tiene la opción "New C# Class". ¿Me pregunto como se habilita esta opción?
¡Hola Platzinauta 👋!
Puedes habilitar esta opción instalando la extensión C# Extensions que te ayudará en muchas otras cosas más para el lenguaje C# :)
Tarea:
Se utiliza un constructor estático para inicializar cualquier dato estático, o para realizar una acción particular que debe realizarse una sola vez. Se llama automáticamente antes de que se cree la primera instancia o se haga referencia a cualquier miembro estático.
_Referencia: _
Clases Estáticas - static class
¿Qué es una static class?
Es aquella clase que no puede ser instanciada y que todos sus miembros son estáticos, propiedades y métodos.
El uso más común es servir para declarar métodos utilitarios generales los cuales no dependen de una instancia de la clase que hospeda el método.
Una de las desventajas es que la clase estática no puede utilizar interfaces.
Al no poderse instanciar tampoco se puede utilizar la inyección de dependencia.
Interesante el uso de los constructores estáticos en clases no estáticas, según comprendo, esto me permite realizar una inicialización en tiempo de ejecución de lo que se puede entender como una "Constante", dado que permite la asignación de a una variable de su mismo tipo "static", se ejecuta una sola vez convirtiéndola en una constante que se inicializa en tiempo de ejecución.
para dejar la valdiación del nulo y el throw en una sola línea:
En python, para tener un atributo private en una clase, en el constructor se lo inicializa como
self.__atributo_privado
Pensé en esto cuando dijo lo de la convención de atributos privados en C#
Una Duda, La manera en que valido el diccionario, es la mas optima??
La primera validación que se hace a un parámetro es determinar si llega nulo, luego dependiendo de la App puedes validar si trae x cantidad de valores, en fin ...
😎
Un proyecto muy interesante
jajaja
Solo yo me reí con ese bug de comunicación ?
He podido utilizar todo en un proyecto personal… falta desplegar en azure y listo
Una clase estática tiene que tener un constructor estático
nameof(), solo devuelve el nombre del objeto?
asi, es por ejemplo en lugar de tener la "cadena" q por ej corresponda a un field en una clase, podrias hacerlo nameof(clase.campo) lo q te devuelve la misma cadena desde un objeto, ademas de que queda mucho mas elegante y profesional, en rendimiento tiende a ser mejor.