Linq y Lambda Expressions

En este caso estaremos viendo una sección de .NET llamada Linq (Language integrated query). Se trata de un conjunto de herramientas para explorar colecciones (arrays, listas, etc.) para obtener elementos o subconjuntos usando lógica. Linq trabaja principalmente con la interfaz genérica IEnumerable<T> que descrine una colección enumerarle de objetos de tipo T.

Con Linq podemos hacer operaciones como agarrar los elementos de la colección que cumplan con ciertas condiciones, ordenar por diferentes atributos, tomar el primer elemento de la colección que cumpla algo, y varias otras cosas.

Las lambda expressions son funciones anónimas declaradas en la línea de ejecución. La estructura de las mismas es definir el nombre de la variable funcional, seguido por el operador de asignacion=>‘ y luego la expresion a evaluar.

2017-09-14 17_28_52-UnityLab - Microsoft Visual Studio
Ejemplo de lambda expression, este código se lee ‘x, tal que x evalúa su propiedad IsEquipped como true’

 

Para ver los siguientes ejemplos, vamos a construir una estructura de clases que podríamos ver comunmente en un RPG para manejar el inventario del personaje.

2017-09-14 17_25_25-UnityLab - Microsoft Visual Studio
Esquema de clases con sus respectivas herencias

Operación First()

First obtiene el primer resultado de la colección, es lo mismo que hacer items[0], en embargo la función First tiene un overload que recibe una expresion lambda, permitiéndonos obtener el primer resultado filtrado en una colección. También existe FirstOrDefault, que devuelve el primer elemento si se encuentra y si no, devuelve un valor por defecto. En caso de objetos este sería null.

2017-09-14 17_25_45-UnityLab - Microsoft Visual Studio
En este caso la función está mal porque devolvería el primer item del inventario.
2017-09-14 17_25_55-UnityLab - Microsoft Visual Studio
Ahora sí, con la lambda expression, esta función va a devolver el primer elemento que encuentre cuyo IsEquipped es true
2017-09-14 17_26_11-UnityLab - Microsoft Visual Studio
Podemos también usar polimorfismo para devolver un hijo de Item por ejemplo
2017-09-14 17_26_30-UnityLab - Microsoft Visual Studio
Y una lambda expression no tiene que estar limitada a una sola condicional, también soporta operadores y varias funcionalidades mas.

 

Operación Where()

Where devuelve un subconjunto de la colección original donde todos los elementos cumplen con la condición dada. Noten el tipo que devuelven estas funciones en comparación con las funciones First(), antes devolvíamos un item, ahora devolvemos una colección numerable de items.

2017-09-14 17_26_47-UnityLab - Microsoft Visual Studio
De esta manera podemos obtener todas las espadas
2017-09-14 17_27_01-UnityLab - Microsoft Visual Studio
Usando una función genérica podemos obtener todos los ítems de un tipo dado.

Generics

Los generics son clases o funciones que reciben uno o más tipos como parámetro para operar sobre ese tipo. Este tipo es genérico y permite gran maleabilidad para crear acoplamiento entre las clases.

 

Operación OrderBy()

Bastante auto explicativa, devuelve la colección ordenada por un criterio dado. Esta operación usa IComparable, de manera que podemos crear comparaciones específicas para objetos complejos. También existe OrderByDecending.

2017-09-14 17_27_26-UnityLab - Microsoft Visual Studio

Operación Union()

Con Union podemos generar una colección nueva a partir de la unión de dos colecciones, los elementos repetidos se van a pasar como uno solo.

2017-09-14 17_27_36-UnityLab - Microsoft Visual Studio

 

Operación Select() y SelectMany()

Select y SelectMany son operaciones un poco mas complejas, el objetivo de esto es obtener un conjunto de cosas que no necesariamente sean del tipo de la colección original. Con select podemos obtener por ejemplo todos los nombres de los ítems sin tener que recorrer la colección para extraer cada uno.

2017-09-14 17_27_46-UnityLab - Microsoft Visual Studio
El resultado de este Select es una colección de strings, La operación Select crea una nueva colección del tipo que sea la propiedad que estamos extrayendo.
2017-09-14 17_27_59-UnityLab - Microsoft Visual Studio
SelectMany se usa cuando la propiedad que queremos extraer es de por si una colección, por ende el resultado va a ser la unión de cada colección extraída por cada ítem.

 

Encadenación de operaciones

Si notan bien, estos métodos devuelven IEnumerables, por ende podemos encadenar varias operaciones, hacer un Where y luego OrderBy en la misma línea por ejemplo. En este código se muestran dos formas de obtener el ítem con mejor categoría en algo.

2017-09-14 17_27_12-UnityLab - Microsoft Visual Studio
Dos formas de hacer lo mismo con Linq

En el primer método obtenemos el valor máximo de nivel dentro de los ítems de ese tipo y luego devolvemos el primer ítem cuyo nivel sea igual al máximo.

En el segundo método, ordenamos la lista de ítems y devolvemos el primero.

Ambas maneras son válidas, cuando hablamos de colecciones gigantes, la primera forma es más eficiente que la segunda.

 

Ejemplo en Unity

¿Como siempre, todo esto es muy útil, pero que uso puede tener en Unity? Bueno de hecho, el manejo de colecciones en juegos es extremadamente común, y si queremos manejar repositorios de recursos en tiempo de ejecución, el buen manejo de colecciones es vital. El siguiente ejemplo es algo que he encontrado sumamente útil y común, se trata de un Spawner, un objeto que inicializa cosas, ya sea enemigos, objetos, powerups, lo que sea, el objeto anida varios otros objetos taggeados como ‘SpawnPoints’ en su jerarquía, y con linq podemos obtener todos esos puntos rápidamente al inicializar el spawner.

 

2017-09-14 17_36_33-marauders_dev - Microsoft Visual Studio
La función GetComponentsInChildren no omite al objeto donde se ejecuta la función, por ende, es un error común que el propio objeto se encuentre a sí mismo. Con linq y tags podemos evitar eso.

De esta manera tenemos nuestra colección armada en la inicialización sin tener que hacerlo manualmente. Lo mejor de todo es que agregar nuevos puntos es tan fácil como duplicar y mover lo que ya tenemos, no se requiere armar referencias ni cambiar nada, el código es completamente automático.

 

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s