Cómo crear un reporteador en C sharp
Clase 24 de 35 • Curso de C# con .Net Core 2.1
Contenido del curso
Etapa 5 – POO reutilicemos nuestro código
- 2

Herencia para reutilizar código C#
10:30 min - 3

Herencia y Polimorfismo en Programación Orientada a Objetos
11:42 min - 4

Polimorfismo en Programación Orientada a Objetos
13:17 min - 5

Casting en C#: cuándo funciona y cuándo falla
07:09 min - 6

Conversiones seguras en C# con is y as
12:44 min - 7

Sobrescribir ToString para depuración en C#
08:15 min
Etapa 6- Ajustes y funcionalidad
Etapa 7 – Preparando información para nuestros reportes
- 11

Manejo Avanzado de Métodos y Parámetros en Programación
15:43 min - 12

Manejo de Parámetros de Salida en Visual Studio Code
04:38 min - 13

Sobrecarga de Métodos para Parámetros de Salida Opcionales
05:51 min - 14

Optimización de Listas: Buenas Prácticas en C#
04:16 min - 15

Dictionary: cómo funciona en C#
11:14 min - 16

Diccionarios con polimorfismo en C#
10:48 min - 17

Uso de Constantes y Enumeraciones para Optimizar Diccionarios en C#
11:33 min - 18

Foreach anidado para diccionarios en C#
13:47 min - 19

Depuración de diccionarios en C#
09:37 min - 20

Parámetro opcional para controlar impresión en C#
11:47 min - 21

Cómo usar switch en lugar de if/else
14:30 min - 22

Números aleatorios y eventos en C#
12:52 min - 23

Diccionarios y Refactoring en Programación Básica
02:13 min
Etapa 8 – Consultas
- 24

Cómo crear un reporteador en C sharp
Viendo ahora - 25

Generación segura de reportes en sistemas de información
10:21 min - 26

Construcción de reportes con LINQ en C#
11:48 min - 27

Diccionario con evaluaciones por asignatura
08:32 min - 28

Tipos anónimos en LINQ para reportes complejos
10:52 min - 29

Cálculo del Promedio de Notas Agrupadas por Alumno y Asignatura
10:46 min - 30

Creación de Tipos de Datos Personalizados en Programación Avanzada
12:05 min - 31

Generación de Reportes con LINQ en C#
02:09 min
Etapa 9 – Creando una UI de Consola
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.