martes, 28 de octubre de 2014
Seguimos con la serie donde vamos desgranando las novedades de C# 6, y en esta ocasión vamos a ver algunas mejoras en el uso de bloques try/catch, a las que seguro podremos sacar buen partido.
En este post trataremos dos temas distintos. En primer lugar, comentaremos la introducción del soporte de
Vamos a ello :-)
Como curiosidad, el motivo de que el uso de
No sé a vosotros, pero a mí incluso me ha sorprendido que no se pudiera hacer antes. Seguro que si no lo he echado en falta es porque no me he encontrado hasta ahora con la necesidad de hacerlo, lo que puede indicar que tampoco es algo habitual (al menos por mi parte, claro) pero bueno, está bien saber que ya podremos usarlo con normalidad.
Aunque este enfoque es válido en muchas ocasiones, hay otras donde sería interesante poder tener un mayor control a la hora de decidir si queremos que un bloque
Para ello, C# 6 incorpora los nuevos exception filters, que son condiciones adicionales que podemos añadir a cada cláusula catch de forma que, si no se cumplen, el bloque será ignorado y se seguirá buscando en el resto de catchs si hay alguno que puedan manejar la excepción.
La sintaxis de estos bloques es la siguiente:
Como podéis observar, la cosa consiste simplemente en añadir condiciones a las cláusulas
Fijaos que con las versiones de C# anteriores a la 6 no sería tan sencillo solucionar este escenario. Nos veríamos obligados a introducir un único
Por supuesto, las condiciones pueden contener cualquier tipo de expresión booleana, como en el siguiente ejemplo:
Y aprovechando esta capacidad, es posible hacer usoy abuso de estos filtros para realizar tratamiento lateral de excepciones, es decir, realizar determinadas tareas cuando una excepción se detecta, pero permitiendo que el resto de catchs sean evaluados. Por ejemplo, en el siguiente código se guardan las excepciones
En definitiva, de nuevo estamos ante unas novedades no muy espectaculares, pero sí útiles para cubrir escenarios que con las versiones anteriores de C# no podíamos solucionar de forma tan directa.
Otros posts de la serie sobre C# 6:
En este post trataremos dos temas distintos. En primer lugar, comentaremos la introducción del soporte de
await
en bloques catch
/finally
, y seguiremos con la nueva capacidad de filtrado de excepciones.Vamos a ello :-)
Soporte de await en bloques catch/finally
Esta nueva característica cubre una pequeña ausencia presente en las versiones anteriores del lenguaje de la que, sinceramente, no me había dado cuenta hasta la fecha. Resulta que en las versiones de C# anteriores a la 6, no estaba permitido utilizarawait
para esperar la finalización de una llamada asíncrona en bloques catch
y finally
. Por tanto, un código como el siguiente lanzaba un error de compilación:Como curiosidad, el motivo de que el uso de
await
no estuviera soportado en este tipo de bloques en las versiones anteriores del lenguaje era simplemente "porque era muy difícil de implementar" (palabras textuales).No sé a vosotros, pero a mí incluso me ha sorprendido que no se pudiera hacer antes. Seguro que si no lo he echado en falta es porque no me he encontrado hasta ahora con la necesidad de hacerlo, lo que puede indicar que tampoco es algo habitual (al menos por mi parte, claro) pero bueno, está bien saber que ya podremos usarlo con normalidad.
Filtros de excepciones
Hasta ahora, la granularidad de los bloquescatch
de C# es a nivel de tipo de excepción. Es decir, tras un try
normalmente encontramos tantos catch
como tipos de excepción distintos queremos controlar, indicando así dónde queremos que se gestione la excepción cuando se produzca. Podemos ver un ejemplo del código habitual en el lateral.Aunque este enfoque es válido en muchas ocasiones, hay otras donde sería interesante poder tener un mayor control a la hora de decidir si queremos que un bloque
catch
concreto gestione una excepción.Para ello, C# 6 incorpora los nuevos exception filters, que son condiciones adicionales que podemos añadir a cada cláusula catch de forma que, si no se cumplen, el bloque será ignorado y se seguirá buscando en el resto de catchs si hay alguno que puedan manejar la excepción.
Nota: efectivamente, esto existe en VB.NET desde el principio de los tiempos. Aunque a veces pueda parecer lo contrario, no siempre C# va por delante ;)
La sintaxis de estos bloques es la siguiente:
Como podéis observar, la cosa consiste simplemente en añadir condiciones a las cláusulas
catch
, de forma que la excepción sólo será tratada en ese bloque si la condición evalúa a cierto. En caso contrario, se continuarán evaluando el resto de catchs hasta encontrar uno capaz de gestionar la excepción. Por ejemplo, en el caso anterior, un una excepción ServerException
cuya propiedad HttpCode
valga 503 será evaluada por el catch
final.Fijaos que con las versiones de C# anteriores a la 6 no sería tan sencillo solucionar este escenario. Nos veríamos obligados a introducir un único
catch
para la excepción ServerException
y decidir en su interior si debemos tratarla, pero en caso contrario no podremos dejarla fluir para que otros catch
posteriores la traten. A lo sumo podríamos relanzarla, pero el resultado tampoco sería el mismo.Por supuesto, las condiciones pueden contener cualquier tipo de expresión booleana, como en el siguiente ejemplo:
Y aprovechando esta capacidad, es posible hacer uso
ServerException
en el log, pero el tratamiento final de la excepción se realizará en el último catch
porque el filtro siempre retorna false
: En definitiva, de nuevo estamos ante unas novedades no muy espectaculares, pero sí útiles para cubrir escenarios que con las versiones anteriores de C# no podíamos solucionar de forma tan directa.
Otros posts de la serie sobre C# 6:
- El operador “?.” en C# y VB.NET, más cerca
- Inicialización de propiedades en C# 6.0
- Uso de miembros estáticos en C# 6, ¿una buena idea?
- Declaración de variables en expresiones de C# 6
- El operador nameof de C# 6 y rendimiento del operador nameof.
- Inicialización de diccionarios en C# 6
1 comentario:
Buen dato, la verdad no lo sabia.
Enviar un nuevo comentario