Jose Axel Diaz Gonzalez
por que modificar el codigo sin grabarlo para la clase?
El valor null es responsable de más errores y fallos en software que cualquier otro concepto en la historia de la programación. Tony Hoare, su creador, lo reconoció públicamente como «el error del billón de dólares» [0:03]. Comprender cómo manejar la anulabilidad segura en C# es fundamental para escribir código robusto y libre de sorpresas en tiempo de ejecución.
¿Por qué null es considerado el error del billón de dólares?
En 1965, Tony Hoare introdujo las null references simplemente porque eran fáciles de implementar. Desde entonces, este valor ha provocado innumerables bugs y crashes en aplicaciones de todo tipo. En C#, la anulabilidad segura permite declarar variables que podrían no tener valor y establecer un valor por defecto para evitar que el programa falle.
Por ejemplo, al declarar una variable de longitud se puede usar el operador de anulabilidad para indicar que el valor alternativo es cero [0:11]. Esto garantiza que, aunque la entrada del usuario esté vacía o sea null, el programa no se rompa.
¿Cómo funcionan trim y tolower en la validación de entrada?
Antes de procesar la entrada del usuario, se aplican dos métodos clave:
Además, se verifica si la entrada es null or empty con string.IsNullOrEmpty() [0:19]. Si se cumple esta condición, se asigna automáticamente un valor por defecto, que en el ejemplo del proyecto es "salir".
¿Qué resultado se obtiene al probar con y sin valor?
Al ejecutar el programa con el valor "doscientos cincuenta", la longitud reportada es tres caracteres y el comando limpio toma el valor ingresado correctamente [0:31]. Al reiniciar y no ingresar ningún valor, la longitud es cero y el código limpio asigna "salir" como respuesta por defecto [0:42]. Esto demuestra que la anulabilidad segura está funcionando como se espera.
¿Cómo se aplica la anulabilidad segura en un proyecto de inventario?
El proyecto de inventario implementa estas técnicas en un flujo real de trabajo. Los comandos disponibles son:
Se utiliza un while que mantiene el sistema activo mientras una variable booleana sea verdadera [0:52]. Dentro del bucle, se lee la entrada del usuario y se declara un string llamado comando que aplica la cadena completa de validación: verifica si es null, ejecuta trim, aplica tolower y, si no hay entrada, asigna "salir" como valor por defecto [1:02].
¿Cómo funciona el switch con los comandos del inventario?
El switch evalúa el valor de comando y ejecuta la acción correspondiente [1:14]:
¿Qué demuestra la ejecución en consola?
Al ejecutar el programa y escribir "salir", el case correspondiente se activa y muestra «Hasta luego» [1:30]. Al usar "listar", el inventario reporta cero productos correctamente [1:37]. Lo más interesante ocurre cuando no se ingresa ningún valor y se presiona enter: el programa asigna automáticamente "salir" gracias a la anulabilidad segura, lo que activa el case de salida e imprime «Hasta luego» [1:44].
Esta implementación confirma que manejar correctamente los valores null desde el diseño del código previene errores silenciosos y hace que la aplicación responda de forma predecible ante cualquier entrada del usuario. Si estás construyendo tus primeros proyectos en C#, prueba a implementar estas validaciones y comparte cómo te fue.
// ============================================================ // SISTEMA DE INVENTARIO - Clase 1.1 // Estado: Mensaje de bienvenida // ============================================================ using System.Reflection; var assembly = Assembly.GetExecutingAssembly(); var version = assembly.GetName().Version; MostarBanner(); if (args.Length > 0) { switch (args[0].ToLower()) { case "--help": MostrarAyuda(); Environment.Exit(0); break; case "--version": Console.WriteLine($"InventarioApp Version: {version}"); Environment.Exit(0); break; default: Console.WriteLine($"Error: comando desconocido '{args[0]}'"); Console.WriteLine("Usa --help para ver las opciones disponibles"); Environment.Exit(2); break; } } int cantidadProductos = 0; decimal valorTotalDelInventario = 0.00m; bool sistemaActivo = true; string nombreSistema = "Sistema de Gestion de Inventario"; /* string? nombre = null; int longitud = nombre.Length; Console.WriteLine($"La longitud del nombre es: {longitud}"); // Problema: readline puede devolver null Console.Write("Ingrese un valor: "); string? entrada = Console.ReadLine(); int? longitud = entrada?.Length; // Solucion Operador coalescing ?? //string comando = string.IsNullOrEmpty(entrada) ? "salir" : entrada; string comandoLimpio = string.IsNullOrWhiteSpace(entrada) ? "salir" : entrada.Trim().ToLower(); Console.WriteLine($"Longitud: {longitud ?? 0}"); Console.WriteLine($"Comando: {comandoLimpio}"); */ Console.WriteLine("Estado del sistema"); Console.WriteLine($"Nombre: {nombreSistema}"); Console.WriteLine($"Cantidad de productos registrados: {cantidadProductos}"); Console.WriteLine($"Valor total del inventario: ${valorTotalDelInventario:N2}"); Console.WriteLine($"Sistema activo: {(sistemaActivo ? "Si" : "No")}"); Console.Write("Ingrese una cantidad: "); string? input = Console.ReadLine(); // Conversion segura TryParse if (int.TryParse(input, out int cantidad)) { Console.Write($"Cantidad valida: {cantidad} \n"); cantidadProductos = cantidad; } else { Console.WriteLine("Error: Dene ingresar un numero entero"); } Console.Write("Ingrese un precio: "); string? inputPrecio = Console.ReadLine(); if (decimal.TryParse(inputPrecio, out decimal precio)) { Console.Write($"Precio valido: {precio} \n"); valorTotalDelInventario = cantidad * precio; Console.WriteLine($"Valor total del inventario: ${valorTotalDelInventario:N2}"); } else { Console.WriteLine("Error: Dene ingresar un numero decimal"); } // Loop de nullabilidad Console.WriteLine("Comandos: listar, agregar, buscar, salir"); Console.WriteLine(); while (sistemaActivo) { Console.Write("inventario: "); string? entrada = Console.ReadLine(); string comando = string.IsNullOrWhiteSpace(entrada) ? "salir" : entrada.Trim().ToLower(); switch (comando) { case "salir": Console.WriteLine("Saliendo del programa..."); sistemaActivo = false; break; case "listar": Console.WriteLine($"Lista de productos: {cantidadProductos}"); break; case "": break; default: Console.WriteLine($"Error: comando desconocido '{comando}'"); Console.WriteLine("Comandos disponibles: listar, agregar, buscar, salir"); break; } } /* Console.Write("Ingrese un comando o ingrese salir para terminar: "); string? comandoSalir = Console.ReadLine(); if (string.IsNullOrWhiteSpace(comandoSalir) || comandoSalir.ToLower() == "salir") { Console.WriteLine("Saliendo del programa..."); Environment.Exit(0); } */ /* Console.WriteLine(); Console.WriteLine("Estructura del proyecto:"); Console.WriteLine("Configuracion .csproj"); Console.WriteLine("Carpet src/ creada"); Console.WriteLine("Metadatos configurados"); Console.WriteLine(); Console.WriteLine("Proximo paso: Agregar argumentos CL y configuracion de repositorio en github"); Console.WriteLine("=========================================="); */ // Funciones void MostarBanner() { Console.WriteLine("=========================================="); Console.WriteLine(" SISTEMA DE GESTIÓN DE INVENTARIO "); Console.WriteLine("=========================================="); Console.WriteLine(); Console.WriteLine($"Version: {version}"); Console.WriteLine($"Plataforma: {Environment.OSVersion}"); Console.WriteLine($".NET Version: {Environment.Version}"); Console.WriteLine(); } void MostrarAyuda() { Console.WriteLine("USO: InventarioApp [comando] [opciones]"); Console.WriteLine(); Console.WriteLine("COMANDOS:"); Console.WriteLine(" --help, -h Muestra esta ayuda"); Console.WriteLine(" --version, -v Muestra la version del programa"); Console.WriteLine(); Console.WriteLine("EJEMPLOS:"); Console.WriteLine(" dotnet run -- --help"); Console.WriteLine(" dotnet run -- --version"); }
Jose Axel Diaz Gonzalez
por que modificar el codigo sin grabarlo para la clase?
Luis Arturo Cruz Cruz
¿Soy solo yo, o es que a veces el profesor no explica las funciones de algunos de los métodos que invoca? como por ejemplo .Trim() ¿lo explico aqui, o en la clase pasada?
Joscelyn Nieves
¿Cuándo debo usar ? en mis variables?
Debes usar el sufijo ? (como en string?) cuando el flujo de tu aplicación genuinamente permita la ausencia de un valor, por ejemplo, al leer datos del usuario o consultar una base de datos. Esto le indica al compilador de C# que te obligue a verificar su estado antes de usarlo, actuando como un escudo protector. Si una variable siempre debe tener datos para que el sistema funcione, no la hagas nulable y exige su valor desde el principio.
Juan Carlos Cantú Ibarra
Hay discrepancia en el codigo por el minuto 4:00.
Ojo el if args length lo tenia antes mas arriba y ahora lo ajusto para que la funcion MostarBanner fuera al inicio.
Solo para que lo tomen en cuenta.
Damian Rengifo
¿Es posible encadenar múltiples operadores ?.?
Sí, es una práctica excelente cuando navegas por objetos complejos con múltiples niveles de profundidad, como cliente?.Direccion?.CodigoPostal. Si en cualquier punto de esa cadena un elemento resulta ser nulo, la evaluación se detiene inmediatamente y toda la expresión devuelve null sin lanzar errores. Esto hace que tu código sea mucho más limpio y fácil de leer, eliminando la necesidad de escribir múltiples bloques if anidados.
Saúl Marcelo Sánchez Santacruz
Mis apuntes:
Kevin Rivas
el "ReadLine" se pronuncia mas como "RidLain" y no "RedLine" eso significaria "Linea Roja"
Lautaro Martinez
Documentación de los operadores vistos en la clase: