En nuestro nuevo curso «Manteniendo la clase con C#», cubrimos lo básico de C# para aquellos que construyen sus primeras aplicaciones de C#. Una vez que lo juegues y adquieras experiencia práctica con este versátil lenguaje, es hora de empezar a explorar sus muchas y útiles funciones, incluyendo algunas que podrían ahorrarte muchos problemas a largo plazo. A continuación, le mostraremos algunos ejemplos de cómo hacer que C# funcione realmente para usted (y algunas ilustraciones de lo que no se debe hacer).
Parámetros opcionales
Un uso común de las sobrecargas de métodos es manejar casos en los que se tienen parámetros que no se requieren. Considere las siguientes sobrecargas de métodos:
AddUser(cadena apellido)AddUser(cadena primerNombre, cadena apellido) AddUser(cadena primerNombre, cadena segundoNombre, cadena apellido)
En última instancia, estos tres métodos crean el objeto de usuario utilizando las cadenas proporcionadas. Mientras que las sobrecargas de los métodos son una opción razonable para esto, hay una forma más legible de hacerlo.
AddUser(cadena apellido, cadena nombreNombre = cadena.Vacía, cadena nombre medio = cadena.Vacía)
En este ejemplo, utilizamos parámetros opcionales en los que, en caso de que no se proporcione un parámetro, le damos un valor por defecto. Esto nos permite consolidar todas estas sobrecargas de métodos en un único método limpio.
Operadores condicionales nulos
A veces el manejo de valores nulos puede convertirse en un verdadero dolor, creando grandes y molestas condiciones para asegurarse de que todo se maneje correctamente. En el siguiente código, nos hemos conectado a una base de datos remota y estamos tratando de manipular algunos registros en una tabla, pero necesitamos hacer muchas comprobaciones nulas para evitar errores de lanzamiento.
if(dbConexión!= nulo && dbConexión.Tabla!= nulo && dbConexión.Tabla.Registros != nulo){ Devuelve dbConexión.Tabla.Registros.Cuenta;}
Es una condición bastante fea. Ahora imagina que estoy comparando dos o más bits separados de información para crear esa condición.
if(dbConexión!= nulo && dbConexión.Tabla1 != nulo && dbConexión.Tabla2 != nulo && dbConexión. Tabla3 != nulo && dbConnection.Tabla1.Registros != nulo && dbConnection.Tabla2.Registros != nulo && dbConnection.Tabla3. Registros != null && dbConnection.Table1.Registros.Recuento == dbConnection.Table2.Registros.Recuento && dbConnection.Table1.Registros.Recuento; dbConnection.Table3.Registros.Recuento){ Devuelve dbConnection.Table1.Registros.Recuento - dbConnection.Table3.Registros.Recuento;}
Estos son el tipo de bloques condicionales de pesadilla que quieres evitar, porque al final lo único que realmente nos importa es si la Tabla1 tiene el mismo número de registros que la Tabla2, y si eso era más registros que la Tabla3.
Afortunadamente, podemos hacer esto más agradable usando operadores condicionales nulos, que nos permiten hacer nuestras comprobaciones nulas de una manera agradable.
if(dbConexión?.Tabla1?.Registros?){ Devuelve dbConexión.Tabla.Registros.Conteo;}
Ahora veamos nuestra condición extrema limpiada usando operadores de condición nula.
if(dbConnection?.Table1?.Records?.Count == dbConnection?.Table2?.Records?.Count && dbConnection?.Table1?.Records?.Count > dbConnection?.Table3?.Records?.Count){ Return dbConnection.Table1.Records.Count - dbConnection.Table3.Records.Count;}
Claro, todavía no es «bonito», pero es mucho más fácil de leer de lo que era sin usar operadores condicionales nulos.
Excepciones de prueba y captura
Aunque normalmente es mejor manejar los errores antes de que ocurran, hay casos en los que es apropiado lanzar una excepción o evitar que una excepción lanzada llegue a un usuario.
Considere el siguiente escenario. Nuestra aplicación está accediendo a un servicio web de terceros. En cualquier momento, ese servicio podría desconectarse, responder de forma inesperada, etc. Mientras escribimos nuestro código esperando que funcione de cierta manera, necesitamos cubrir nuestras bases en caso de que se comporte de manera inesperada.
Tenemos varias opciones sobre cómo podríamos manejar esto:
Deje que el usuario vea el error
Var resultados = (BoardGame)WebService.ReadToEnd();
Cuando el servicio web se comporta mal, nuestros usuarios se enfrentan a un mensaje de error. Si tienes suerte, algo registró el error, pero es muy probable que nada lo haya hecho, así que ni siquiera te darías cuenta de que algo salió mal hasta que alguien se queje. No es una buena manera de hacer las cosas.
Errores de captura y deglución
Try{ Resultados de Var = (BoardGame)WebService.ReadToEnd();}Catch(Excepción ex){ // no hacer nada}
Esto es posiblemente incluso peor que arrojar errores al usuario. En este caso, algo salió mal, pero para el usuario parece que todo va bien! Esto puede causar todo tipo de problemas, como hacer que el usuario piense que ha pagado con éxito un pedido. Generalmente, no hay peor forma de manejar los errores que simplemente hacer que los errores «desaparezcan».
Manejar los errores
Try{ Var resultados = (BoardGame)WebService.ReadToEnd();}}Catch(Excepción ex){ Logger.Log(ex); DisplayUserFriendlyErrorMessage();}
OK, mejorando. Para muchas situaciones, la práctica estándar es proporcionar al usuario un mensaje como, «Algo salió mal-por favor, inténtelo de nuevo más tarde» y luego registrar el error para revisarlo más tarde. Si el error es lo suficientemente malo, regístralo y notifica inmediatamente a quien sea responsable de la aplicación para que pueda solucionarlo lo antes posible.
Manejar errores específicos
Try{ Var resultados = (BoardGame)WebService.ReadToEnd();}Catch(TimeOutException ex){ Logger.Log(ex, Severity.Medium); Alert(Staff.IT); DisplayCachedDataToUser();}Catch(InvalidCastException ex){ Logger. Log(ex, Severidad.Crítica); Alerta(Staff.Developers); DisplayErrorToUser();}Catch(Excepción ex, Severidad.Alta){ Logger.Log(ex); Alerta(Staff.Everyone); DisplayErrorToUser();}
Nuestro último ejemplo es una mejor manera de manejar las cosas. En todos los casos, registramos el error y proporcionamos una gravedad, alertamos al personal apropiado y proporcionamos algún tipo de retroalimentación al usuario.
Si obtenemos un TimeOutException, significa que el servicio web tardó demasiado en responder, así que lo registramos, avisamos a TI de que podríamos tener problemas de red con detalles de errores y mostramos los datos de la última vez que llamaron al servicio.
Si tenemos una excepción de InvalidCast, podría ser grave. Esto significa que los datos que el servicio web nos proporcionó no son los que esperábamos, por lo que se rompe nuestra aplicación. En este caso, nuestra aplicación se rompe hasta que podamos adaptarnos al cambio, lo que significa que podríamos necesitar que los desarrolladores respondan inmediatamente.
Por último, si aún así obtenemos un error, pero no es uno que hayamos planeado, registramos el error, avisamos a todos (ya que no estamos seguros de quién debe solucionarlo) y proporcionamos un error del tipo «Inténtalo de nuevo en una fecha posterior» al usuario.
Al final, lo importante es no enterrar u ocultar nunca un error. Por lo menos, querrás registrar el error en algún lugar. Incluso mejor: Predecir y manejar los errores para que llamen la atención de quienes necesitan abordar el problema, así como los detalles, para que puedan responder de la mejor manera posible.
Estas son sólo algunas de las incontables características disponibles en C#. Cuanto más se investigue sobre las características de un idioma y se conozca la funcionalidad disponible, más fácil será escribir un código limpio, eficiente y eficiente (y con suerte, encontrar el menor número de errores posible). Juega a nuestro curso Keeping It Classy With C# para aprender aún más y obtener experiencia de primera mano en la construcción de una aplicación en C#. O echa un vistazo a nuestro completo post sobre todo lo que necesitas saber sobre C#.