Esta segunda entrega de novedades de C# 6.0, la vamos a utilizar por completo para explicar el Null Conditional Operator (.?) o
Evaluador de null en código. Parte
de este operador, ya era un viejo conocido, utilizado en versiones anteriores,
para realizar operaciones ternarias
y en conjunción doble para tratamientos de valores nulos en tipos por referencia y en tipos nullables. En esta nueva versión, toma de nuevo protagonismo al
vincularse con el punto (.) y nos intenta hacer la vida un poquito más fácil.
Vamos a ver de qué va.
Entregas anteriores de novedades C# 6.0
Parte 2
Para estos ejemplos vamos a ayudarnos de una versión de
nuestra clase favorita de pruebas, que no es otra que la clase Persona, en esta ocasión, la
utilizaremos en conjunción de la clase Direccion,
que formará parte de su composición:
Comparaciones con NULL
Normalmente, dentro de nuestros métodos, deberíamos de
comprobar para cada uno de los parámetros de tipos por referencia, si estos,
han sido instanciados, vamos si no tienen el valor null, porque de realizar esta comprobación, se producirá
nuestra excepción favorita:
Pongamos un ejemplo de un método en el que controlamos la
instanciación de nuestros parámetros:
Este método
simplemente comprueba que una persona sea de ese maravilloso paraje imaginario
llamado ‘Valdenalga’. Para
ello tenemos que comprobar que la referencia principal del parámetro de tipo persona, no sea nula. No nos podemos
conformar con eso, porque su propiedad Dirección,
también es de tipo referencia, por lo que deberemos comprobar que esté igualmente
instanciada. Una vez seguros ya podemos acceder a Localidad.
Llega el momento de emplear la novedad a la que dedicamos
este post, como veremos reduciremos el tamaño del código y aumentaremos la
compresión del mismo. Lo iremos haciendo por fases, para comprender mejor el
funcionamiento.
Primero eliminaremos la comprobación de null, para la propiedad de tipo Dirección, y haremos uso de nuestro operador en la verificación
de localidadABuscar, quedando así:
Esta es la línea clave:
persona.Direccion?.Localidad == localidadABuscar
Cuando la ejecución llega a esta línea, lo que hace el
compilador es comprobar si el objeto que está con anterioridad al símbolo ? es null. En caso de serlo, simplemente se olvida de todo lo demás
y devuelve un null. En caso
negativo continúa con la ejecución, como en nuestra línea, accediendo a la
propiedad Localidad y
realizando la comprobación con localidadABuscar.
Bueno y si hemos hecho esto con la última comprobación del if, por qué no hacer lo mismo con la
primera ¿?. Pues claro:
Pues este es el método de desenlace, así pinta de bien.
Accediendo a métodos y a propiedades
Con el uso de este operador, podemos hacer llamadas a
métodos y acceder a propiedades de objetos sin instanciar.
Vamos a actualizar nuestra clase persona, con unos cuantos
métodos:
Si alguno ve rara la definición de los métodos, que se
repase nuestra primera
entrega de novedades de C# 6.0.
En esta nueva versión, podremos hacer cosas como estas:
Como explicamos en el punto anterior, el compilador, se
encuentra con el símbolo ‘?’
y comprueba si el objeto a su izda es nulo,
para realizar o no la acción. Por lo que en este caso no ejecutaría nada, y no
lanzaría excepción.
Si nos ponemos serios, esto no tiene ninguna funcionalidad,
pero solo lo he plasmado aquí para que lo probéis y veáis que no paraliza la
ejecución. Debemos de tener cuidado al
hacer uso de código de este tipo, porque no tendremos ninguna constancia de si
esto se ha ejecutado o no.
De idéntica manera se comportará el acceso a las propiedades
del objeto, dándonos como resultado un null
cada vez que accedamos a una propiedad de un objeto sin instanciar:
Puede parecer que no es nada útil, pero veremos que en momentos
nos puede ahorrar escribir ese código en ocasiones tan tedioso que es el de las
comprobaciones.
En conjunción con el operador ??
Voy a hacer un pequeño resumen de este operador, por si
alguien lo desconoce, para que pueda entender mejor este punto, en caso de
conocerlo, sáltatelo sin problema.
Este operador básicamente es consumido en las asignaciones y no puede ser
utilizado con los tipos por valor (struct),
solo puede ser empleado por los tipos por
referencia y por los tipos nullables,
siendo estos últimos con los que más se usa.
Creo que los comentarios lo dejan bastante claro, pero si
alguien sigue teniendo algún tipo de duda, dejo aquí el
enlace a la MSDN.
Volviendo a lo que nos importa para este post, vamos a ver
la mezcla de estos dos operadores y como esto sí que nos va a hacer ver un
poquito más de color y de utilidad.
Como hemos aclarado ya unas cuantas veces en lo que llevamos
de post, cuando accedemos a cualquiera de los miembros de un objeto sin
instanciar mediante ‘?.’,
este devuelve el valor null.
Esto ocurre indistintamente tanto si lo hacemos a Métodos, Propiedades,
etc. Vamos a demostrarlo:
Como vemos en la imagen, estamos intentando asignar el resultado de la propiedad Edad, que es de tipo int, a una variable edad igualmente de tipo int, y el compilador no nos deja elaborar la acción cuando utilizamos el operador ‘?.’. Esto se debe a que sabe que por mucho que la propiedad o la firma del método den como resultado un tipo no nullable, a usar este operador, el desenlace puede ser null, por lo que no tiene cabida dentro de un objeto System.Int32. Por eso nos dice que no puede realizar la conversión a un int? (Nullable<int>) de manera explícita.
Para no tener que inicializarlo en variables nullables y
luego tener que preguntar si tienen valor y … … … (rolletes), unificaremos su
uso con el operador ?? y nos ahorramos trabajo, dejando nuestro código mucho
más bonito. Así quedaría el ejemplo anterior:
En definitiva mucho más legible y mucho más de estos tiempos
que corren.
Para que todo no sean tipos nullables, voy a poner un ejemplo con una clase, y dentro de un
método. Esto cobra mucho más sentido, porque nadie en su sano juicio (debería)
va a instanciar una propiedad a null
y se va a poner a utilizarla. Cuando el valor de la clase viene por parámetros,
no sabemos nunca con veracidad que este haya sido instanciado.
LINQ
Esto también tiene su introducción en el mundo de LinQ, por ejemplo para saber si una
colección tiene elementos:
O mediante la utilización de cualquier operador _OrDefault (FirstOrDefault, SingleOrDefault,
etc):
En uso para eventos
Otra de las comodidades que nos ofrece el operador ?., es el uso con los manejadores de eventos. Como todos sabemos, cuando implementamos un evento
dentro de nuestra clase, siempre antes de lanzarlo en nuestro código, debemos
de preguntar si alguien se ha suscrito a él, ósea tenemos preguntar si el valor
de su delegado es null. Con el operador .? nos
libraremos de este lastre.
Vamos a añadir a nuestra clase Persona, un evento
que se lance cuando una persona tenga más de 18 años. Ya hicimos algo parecido
en nuestra entrada de Eventos del curso de LinQ,
lo podemos repasar aquí
. La clase quedaría así:
Para ello hemos añadido un evento de tipo EventHandler
(evento simple del Framework, que realiza una acción y solo informa del objeto
que realiza la acción). Y con él un método On(NombreEvento),
que será posible redescribir por sus
clases derivadas (esto lo
deberían de tener todos los eventos).
En este método haremos la comprobación de suscripción, para no tener que realziarla
en cada llamada al evento.
Después en el set de la propiedad Edad,
comprobaremos si tiene más de 18 años para lanzar nuestro evento MayorDeEdad, mejor dicho nuestro
método OnMayorEdad, que es
el que encapsula la llamada
al evento.
Nosotros nos centraremos en el método OnMayorDeEdad, y en su comprobación de null. Como llevamos viendo en todo este post, con el operador ?. en caso de que el objeto o la
propiedad sea null, esta no se accederá/lanzará y por ende
devolverá un null. Con los eventos
es algo parecido, pero con una diferencia. Esta diferencia radica en que el
posible valor null, no es el del objeto
‘padre’, es el del evento perteneciente al objeto padre.
Para poder tomar ventaja de esto, no llamaremos directamente
al delegado del evento como en el
código anterior, utilizaremos otra fórmula equivalente, que nos permita utilizar
el operador. La fórmula es emplear el
método Invoke del delegado subyacente al evento, que es igual de válido, y
que nos permite introducir el operador ?.
entre el evento (que es el
objeto que puede estar en null)
y el método (Invoke) a llamar para
ejecutar. Aquí
tenéis más información sobre los delegados
y sus formas de ejecución, tanto síncronas
como asíncronas.
Si alguien se hubiera suscrito se lanzará el evento, y si no, no se haría nada,
sin necesidad de tener que indicar el if.
Como no me gusta que se quede nada en el aire, pondré el
ejemplo original (con if)
utilizando Invoke, en la llamada
del evento:
Igual de funcional.
Pues hasta aquí este post, con Null Conditional Operator. Tenía en mente haber puesto algún ejemplo de WPF, para cuando utilizamos CommandBindings, y estos realizan
comprobaciones (CanExecute) dentro de
la ventana antes de que se hayan creado los controles, en este caso nuestro
operador de hoy también nos ayuda y mucho. El método Find() de los DbSet
de EntityFramework 4.2 y posterior,
también se beneficia de ello, pero creo que ya ha sido el post lo bastante
largo, como para hacerlo un poquito más pesado.
En el siguiente seguiremos con más novedades de nuestro C# 6.0.
No hay comentarios :
Publicar un comentario