martes, 10 de junio de 2014

Expresiones Lambda en C# - Parte 3: Expresiones Lambda y LINQ

Tabla de Contenido

0. Introducción
1. Introducción a LINQ
2. LINQ y Expresionese Lambda
2.1 Ejemplo introductorio
2.2 Predicado, selección, y ordenamiento
3. Conclusiones
4. Glosario
5. Literatura & Enlaces

0. Introducción

Esta entrega corresponde con la tercera parte de la serie de artículos de expresiones lambda en C#. En esta oportunidad nos adentraremos en el uso de expresiones lambda en combinación con el lenguaje de consulta de .NET: LINQ. Exploraremos varios de los métodos de las colecciones sobre los que podemos pasar una expresión lambda para establecer el predicado (condición), el ordenamiento de los elementos, y la selección de elementos.

1. Introducción a LINQ

LINQ (Language-Integrated Query) es un lenguaje de consulta de objetos en memoria, bases de datos, y XML (Extensible Markup Language) integrado en .NET desde la versión 3.5. Este lenguaje de consulta es independiente de la fuente de datos, es decir, que contamos con un único lenguaje que nos permite hacer consultas sobre cualquier fuente de datos sin tener que aprender cada uno de los lenguajes disponibles (XQuery para XML, SQL para bases de datos).

Además de su definición, veamos un ejemplo:

Archivo de código fuente IntroLINQ.cs [enlace alternativo]:

En el código fuente se especifican tres pasos esenciales para el uso de LINQ; los cuales consisten en:
  1. Especificación de una fuente de datos:

    - Colecciones
    - Bases de datos
    - Archivo XML
  2. Diseño de la consulta:

    - Uso de las construcciones where, from, in, select, entre otras más. (Aquí es donde nos interesa hacer uso de las expresiones lambda).
  3. Ejecución de la consulta: Como indican en [6], las consultas no se ejecutan en tiempo de diseño (paso anterior), sino en la región de enumeración elementos, un método, o cualquiera otra sentencia que haga uso explícito de los datos. En el código de ejemplo, en la línea 18.
En la Figura 1 [6] se ilustra gráficamente este proceso.
Ciclo de una consulta LINQ
Figura 1. Ciclo de una consulta LINQ [6].
Por otro lado, en el siguiente fragmento de código C#, vemos cómo especificar otro tipo de fuente de datos (una base datos en archivo), y enseguida el diseño de la consulta con el juego de artefactos sintácticos de LINQ:

// Especificación de la fuente de datos:
Contabilidad dbContabilidad = new Contabilidad(@"c:\contabilidad.mdf");

// Consulta para empleados que tienen una
// edad igual o superior a 30:
IQueryable<Empleado> consulta =
from empleado in dbContabilidad.Empleados
where empleado.Edad >= 30
select empleado;

Para quienes ya hayan trabajado con el lenguaje de consulta estructurado SQL, la estructura de esta consulta les puede ser muy familiar. La ventaja, vuelvo a repetir, de LINQ es que sólo debemos dominar un único lenguaje de consulta, y éste lo podemos emplear para realizar consultas (valga el pleonasmo) sobre cualquier fuente de datos.

[Nota: Futuros artículos tratarán con mayor profundidad este amplio tema de diseño de consultas con LINQ. Sin embargo, en las y recetas podrán encontrar más información sobre este lenguaje de consulta: Receta No. 1-18 en C#: Creación de un Tipo AnónimoReceta No. 2-9 en C#: Ordenar un Arreglo o una ColecciónReceta No. 2-17 en C#: Selección de Elementos de un Arreglo o ColecciónReceta No. 2-18 en C#: Remoción de Elementos Duplicados en un Arreglo o en una Colección
.]

2. LINQ y Expresiones Lambda

Las expresiones lambda pueden ser usada para la especificación del predicado, modo de ordenamiento, selección, etc. Veamos en las siguientes secciones cómo lograrlo.

2.1 Ejemplo introductorio

En el siguiente ejemplo se ilustra el uso de las expresiones lambda para generar un listado de las cadenas almacenadas en un arreglo diferentes de de null.

Archivo de código fuente ExpLambdaLinq.cs [enlace alternativo]:

En la línea 11 crea un arreglo de cadenas de caracteres. Más adelante, en la línea 2 diseñamos una consulta sobre el método Where. Este método recibe como parámetro un predicado. Este predicado consiste en una expresión lambda, en el ejemplo es de la siguiente manera:

cadena => cadena != null


Con esta expresión lambda estamos creando la condición o predicado que indica que sólo se deben retornar los elementos del arreglo blog que sean distintos de null. Existen predicados alternativos para obtener el mismo resultado, como ocurre en la línea 24:

cadena => !string.IsNullOrEmpty(cadena)


La parte derecha de la expresión lambda señala que si el elemento del arreglo blog no (operador unario lógico de negación !) es null o no es una cadena vacía, se debe incluir en el resultado de la consulta.

Este ejemplo nos ha demostrado el uso básico de predicados con expresiones lambda, pasemos a otro en donde podemos especificar el predicado, el modo de ordenamiento, y de selección usando delegados genéricos integrados, precisamente, los de categoría Func (Expresiones Lambda en C# - Parte 3: Expresiones Lambda y LINQ).

2.2 Predicado, ordenamiento, y selección

Un predicado conforma la condición de una consulta; tiene que ver la resolución a valores lógicos de falso y verdadero. El método de ordenamiento consiste en establecer un orden natural (alfabético, numérico, temporal) de los elementos generados por una consulta; la selección indica cuáles elementos del resultado de la consulta deben generarse. En el siguiente código de conceptualización y demostración vamos a ver cada de éstos:

Precidado:

List<int> numeros = List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

// Predicado:
Func<int, bool> where = n => n < 6;


Este predicado -que hemos nombrado where- consta de las siguientes partes:
  • Delegado genérico integrado Func<T, TResult> [7, 10] con los tipos concretos:

    - int: indica el tipo de dato del tipo de parámetro de entrada.
    - bool: tipo de retorno: true (la condición se cumple), de lo contrario false (la condición no se cumple).

  • La expresión lambda:

    n => n < 6;

    El parámetro es inferido al tipo numérico
    int, la expresión como es requerido, retorna uno de dos valores (dependiendo de n): true o false.
En resumen, con esta especificación indicamos que la consulta LINQ bajo la expresión lambda debe generar números menores que 6.

Selección:

// Selección:
Func<int, int> select = n => n;

La variable delegado select está compuesta por:
  • Delegado Func<int, int>:

    - Parámetro
    int.
    - Tipo de retorno
    int.
  • Expressión lambda:

    n => n

    n es inferido como tipo
    int, el tipo de retorno es de la misma naturaleza.
Con la sentencia completa estamos indicando que los elementos retornados por la consulta consiste en números enteros.

Ordenamiento:

// Ordenar por:
Func<int, string> orderby = n => n % == 0 ? "even" : "odd";


La variable delegado orderby se usa como argumento para el método OrderBy [9]. Los elementos se ordenan, en este caso, en este caso por la paridad (impar o par).

Ejemplo completo:

Archivo de código fuente LinqExpresionLambda.cs [enlace alternativo]:

> Prueba de ejecución.

Resultado:
Ejecución ejemplo de LINQ con expresiones lambda
Figura 2. Ejecución ejemplo de LINQ con expresiones lambda.

3. Conclusiones

Hemos descubierto otras de las posibilidades que podemos alcanzar con el uso de expresiones lambda en conjugación con el lenguaje de consulta LINQ. En los ejemplos expuestos se demostró que las expresiones lambda ayudan a simplificar la especificación de predicados (condiciones), método de selección y ordenamiento sobre los métodos Where, OrderBy y Select de la clase Enumerable (N:System.Linq).

Glosario

  • .NET
  • Delegado
  • Delegado genérico integrado
  • Expresión lambda
  • LINQ
  • Tipo

Literatura & Enlaces

[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[2]: Basics of LINQ & Lamda Expressions - CodeProject - http://www.codeproject.com/Articles/33769/Basics-of-LINQ-Lamda-Expressions
[3]: LINQ Tutorial #2 - About Lambda Expressions - http://cplus.about.com/od/learnc/a/Linq-Tutorial-Two-Lambda-Expressions.htm
[4]: XQuery - Wikipedia, the free encyclopedia - http://en.wikipedia.org/wiki/XQuery
[5]: SQL - Wikipedia, the free encyclopedia - http://en.wikipedia.org/wiki/SQL
[6]: Introduction to LINQ Queries (C#) - http://msdn.microsoft.com/en-us/library/bb397906.aspx
[7]: Func(T, TResult) Delegate (System) - http://msdn.microsoft.com/en-us/library/bb549151(v=vs.110).aspx
[8]: Enumerable.Select(TSource, TResult) Method (IEnumerable(TSource), Func(TSource, TResult)) (System.Linq) - http://msdn.microsoft.com/en-us/library/bb548891(v=vs.110).aspx
[9]: Enumerable.OrderBy(TSource, TKey) Method (IEnumerable(TSource), Func(TSource, TKey)) (System.Linq) - http://msdn.microsoft.com/en-us/library/bb534966(v=vs.110).aspx
[10]: Enumerable.Select(TSource, TResult) Method (IEnumerable(TSource), Func(TSource, TResult)) (System.Linq) - http://msdn.microsoft.com/en-us/library/vstudio/bb548891(v=vs.100).aspx


J

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.