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.
Recursos
Resumen
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.
Ejemplo base de la clase:
using System; using System.Collections.Generic; namespace CoreEscuela.App { public class Reporteador { private readonly Dictionary<TipoEntidad, IEnumerable<ObjetoEscuela>> _diccionario; public Reporteador(Dictionary<TipoEntidad, IEnumerable<ObjetoEscuela>> diccionario) { _diccionario = diccionario ?? throw new ArgumentNullException(nameof(diccionario)); } } }
¿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.
- Mensaje auto-documentado con nameof.
Fragmento ilustrativo:
public Reporteador(Dictionary<TipoEntidad, IEnumerable<ObjetoEscuela>> diccionario) { _diccionario = diccionario ?? throw new ArgumentNullException(nameof(diccionario)); }
¿Cómo organizar campos privados y namespaces?
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 = new Reporteador(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.
Ejemplo de constructor estático válido:
class Curso { static Curso() { // Inicialización estática. } }
¿Cuáles son las reglas del constructor estático?
- Sin parámetros: configuración única y automática.
- 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:
public IEnumerable<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.