La ejecución perezosa o diferida (Lazy Loading) es el
comportamiento por defecto que usa LinQ para ejecutar, valga la redundancia,
sus métodos extensores. A grandes rasgos viene a significar que los métodos no
se ejecutan en el momento de realizar su llamada, sino que se ejecutan en el
momento en que consumimos (utilizamos) alguno de los datos devueltos por esta
llamada. Con todo esto el motor de LinQ se asegura el no realizar cálculos,
cargas de datos, etc., que el usuario no necesite en ese momento.
Recuerda que aquí tienes el indice de todos los posts del Curso de LinQ.
Vamos a ver como se produce toda esta magia.
Para ello empezaremos explicando la manera de realizar
nuestros métodos ‘enumerables’
mediante la palabra reservada yield
return.
Para entender desde cero su funcionamiento vamos a hacer un
ejemplo completo, y para ello vamos construirnos un método extensor enumerable. El método será muy
sencillito y extenderá la clase string
agregando la funcionalidad de devolver cada una de las letras de una palabra,
en valores string y no char como realiza por defecto, lo
llamaremos ToEnumerableString.
Cuando nos metemos en la implementación de uno de estos
métodos, debemos olvidarnos del enfoque clásico de me creo una colección de
resultado, la relleno y la devuelvo, ya que en nuestros métodos enumerables lo que haremos será ir
devolviendo los valores que forman la colección, elemento a elemento.
Como podemos comprobar nuestro método devuelve un IEnumerable<string>, y cada
vez que está a disposición de tener listo un elemento, lo devuelve con la
cláusula Yield Return (en un
método que devolvería una colección, este sería el momento en que añadiríamos
elemento a la colección de resultado).
Una vez tenemos el método extensor vamos a ver un ejemplo de
uso con carga perezosa, para ver su funcionamiento es muy importante copiar el
código y jugar con el F11 o poner un punto de
ruptura en el método extensor para ver el momento en que la
ejecución entra en el método.
Como podemos ver, en el momento en que llama al método nombre.ToEnumerableString(), no
realiza la ejecución del mismo, no es hasta su uso dentro del foreach que el compilador traslada
la ejecución a nuestro método extensor, en nuestro ejemplo 4 llamadas, una por
cada una de las letras de “Paco”. Por lo que no se utiliza hasta que es
necesario.
Vamos a ver ahora un ejemplo modificado en el que solo
imprimiremos la primera palabra, y podremos comprobar que solo hace una única
llamada al método extensor, por lo que ahorrará recursos y tiempo en no tener
que realizar la carga de los otros 3 caracteres.
Todos los métodos extensores de LinQ utilizan esta técnica,
que en ocasiones cuando realicemos consultas cruzadas, veremos que no es tan
buena como puede parecer, ya que puede realizar repeticiones de llamadas
innecesarias. Todo esto lo paliaremos con los métodos extensores ToList() y ToArray(), que obligaran a realizar la ejecución del método
completo y que veremos más adelante.
No hay comentarios :
Publicar un comentario