Sintaxis de consultas y sintaxis de métodos en LINQ (C#)Query Syntax and Method Syntax in LINQ (C#)

La mayoría de las consultas de la documentación introductoria de Language Integrated Query (LINQLINQ) se escribe con la sintaxis de consulta declarativa de LINQ.Most queries in the introductory Language Integrated Query (LINQLINQ) documentation are written by using the LINQ declarative query syntax. Pero la sintaxis de consulta debe traducirse en llamadas de método para .NET Common Language Runtime (CLR) al compilar el código.However, the query syntax must be translated into method calls for the .NET common language runtime (CLR) when the code is compiled. Estas llamadas de método invocan los operadores de consulta estándar, que tienen nombres tales como Where, Select, GroupBy, Join, Max y Average.These method calls invoke the standard query operators, which have names such as Where, Select, GroupBy, Join, Max, and Average. Puede llamarlas directamente con la sintaxis de método en lugar de la sintaxis de consulta.You can call them directly by using method syntax instead of query syntax.

La sintaxis de consulta y la sintaxis de método son idénticas desde el punto de vista semántico, pero muchos usuarios creen que la sintaxis de consulta es mucho más sencilla y fácil de leer.Query syntax and method syntax are semantically identical, but many people find query syntax simpler and easier to read. Algunos métodos deben expresarse como llamadas de método.Some queries must be expressed as method calls. Por ejemplo, debe usar una llamada de método para expresar una consulta que recupera el número de elementos que cumplen una condición especificada.For example, you must use a method call to express a query that retrieves the number of elements that match a specified condition. También debe usar una llamada de método para una consulta que recupera el elemento que tiene el valor máximo de una secuencia de origen.You also must use a method call for a query that retrieves the element that has the maximum value in a source sequence. La documentación de referencia de los operadores de consulta estándar del espacio de nombres System.Linq generalmente usa la sintaxis de método.The reference documentation for the standard query operators in the System.Linq namespace generally uses method syntax. Por consiguiente, incluso cuando empiece a escribir consultas de LINQLINQ, resulta útil estar familiarizado con cómo se usa la sintaxis de método en consultas y en las propias expresiones de consulta.Therefore, even when getting started writing LINQLINQ queries, it is useful to be familiar with how to use method syntax in queries and in query expressions themselves.

Métodos de extensión de operador de consulta estándarStandard Query Operator Extension Methods

En el ejemplo siguiente se muestra una expresión de consulta sencilla y la consulta equivalente desde el punto de vista semántico que se escribe como consulta basada en métodos.The following example shows a simple query expression and the semantically equivalent query written as a method-based query.

class QueryVMethodSyntax
{
    static void Main()
    {
        int[] numbers = { 5, 10, 8, 3, 6, 12};

        //Query syntax:
        IEnumerable<int> numQuery1 = 
            from num in numbers
            where num % 2 == 0
            orderby num
            select num;

        //Method syntax:
        IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);

        foreach (int i in numQuery1)
        {
            Console.Write(i + " ");
        }
        Console.WriteLine(System.Environment.NewLine);
        foreach (int i in numQuery2)
        {
            Console.Write(i + " ");
        }
        
        // Keep the console open in debug mode.
        Console.WriteLine(System.Environment.NewLine);
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }
}
/*
    Output:
    6 8 10 12
    6 8 10 12
 */

El resultado de los dos ejemplos es idéntico.The output from the two examples is identical. Como puede ver, el tipo de variable de consulta es el mismo en ambos formularios: IEnumerable<T>.You can see that the type of the query variable is the same in both forms: IEnumerable<T>.

Para entender la consulta basada en métodos, vamos a examinarla más detenidamente.To understand the method-based query, let's examine it more closely. En el lado derecho de la expresión, observe que la cláusula where ahora se expresa como un método de instancia en el objeto numbers, que, como recordará, tiene un tipo de IEnumerable<int>.On the right side of the expression, notice that the where clause is now expressed as an instance method on the numbers object, which as you will recall has a type of IEnumerable<int>. Si está familiarizado con la interfaz genérica IEnumerable<T>, sabe que no tiene un método Where.If you are familiar with the generic IEnumerable<T> interface, you know that it does not have a Where method. Pero si se invoca la lista de finalización de IntelliSense en el IDE de Visual Studio, verá no solo un método Where, sino muchos otros métodos tales como Select, SelectMany, Join y Orderby.However, if you invoke the IntelliSense completion list in the Visual Studio IDE, you will see not only a Where method, but many other methods such as Select, SelectMany, Join, and Orderby. Estos son todos los operadores de consulta estándar.These are all the standard query operators.

Captura de pantalla en la que se muestran todos los operadores de consulta estándar de IntelliSense.

Aunque parece que IEnumerable<T> se haya redefinido para incluir estos métodos adicionales, en realidad no es el caso.Although it looks as if IEnumerable<T> has been redefined to include these additional methods, in fact this is not the case. Los operadores de consulta estándar se implementan como un nuevo tipo de método denominado método de extensión.The standard query operators are implemented as a new kind of method called extension methods. Los métodos de extensión "extienden" un tipo existente; se pueden llamar como si fueran métodos de instancia en el tipo.Extensions methods "extend" an existing type; they can be called as if they were instance methods on the type. Los operadores de consulta estándar extienden IEnumerable<T> y esta es la razón por la que la puede escribir numbers.Where(...).The standard query operators extend IEnumerable<T> and that is why you can write numbers.Where(...).

Para empezar a usar LINQLINQ, lo único que realmente debe saber sobre los métodos de extensión es cómo incluirlos en el ámbito de la aplicación mediante el uso correcto de directivas using.To get started using LINQLINQ, all that you really have to know about extension methods is how to bring them into scope in your application by using the correct using directives. Desde el punto de vista de la aplicación, un método de extensión y un método de instancia normal son iguales.From your application's point of view, an extension method and a regular instance method are the same.

Para obtener más información sobre los métodos de extensión, vea Extension Methods (Métodos de extensión).For more information about extension methods, see Extension Methods. Para obtener más información sobre los operadores de consulta estándar, vea Información general sobre operadores de consulta estándar (C#).For more information about standard query operators, see Standard Query Operators Overview (C#). Algunos proveedores de LINQLINQ, como LINQ to SQLLINQ to SQL y LINQ to XMLLINQ to XML, implementan sus propios operadores de consulta estándar y otros métodos de extensión además de IEnumerable<T>.Some LINQLINQ providers, such as LINQ to SQLLINQ to SQL and LINQ to XMLLINQ to XML, implement their own standard query operators and additional extension methods for other types besides IEnumerable<T>.

Expresiones lambdaLambda Expressions

En el ejemplo anterior, observe que la expresión condicional (num % 2 == 0) se pasa como argumento insertado al método Where: Where(num => num % 2 == 0). Esta expresión insertada se denomina expresión lambda.In the previous example, notice that the conditional expression (num % 2 == 0) is passed as an in-line argument to the Where method: Where(num => num % 2 == 0). This inline expression is called a lambda expression. Se trata de una forma cómoda de escribir código que, de lo contrario, tendría que escribirse de forma más compleja como un método anónimo, un delegado genérico o un árbol de expresión.It is a convenient way to write code that would otherwise have to be written in more cumbersome form as an anonymous method or a generic delegate or an expression tree. En C#, => es el operador lambda, que se lee como "va a".In C# => is the lambda operator, which is read as "goes to". La num situada a la izquierda del operador es la variable de entrada que corresponde a num en la expresión de consulta.The num on the left of the operator is the input variable which corresponds to num in the query expression. El compilador puede deducir el tipo de num porque sabe que numbers es un tipo IEnumerable<T> genérico.The compiler can infer the type of num because it knows that numbers is a generic IEnumerable<T> type. El cuerpo de la expresión lambda es exactamente igual que la expresión de la sintaxis de consulta o de cualquier otra expresión o instrucción de C#; puede incluir llamadas de método y otra lógica compleja.The body of the lambda is just the same as the expression in query syntax or in any other C# expression or statement; it can include method calls and other complex logic. El "valor devuelto" es simplemente el resultado de la expresión.The "return value" is just the expression result.

Para empezar a usar LINQLINQ, no es necesario emplear muchas expresiones lambda.To get started using LINQLINQ, you do not have to use lambdas extensively. Pero determinadas consultas solo se pueden expresar en sintaxis de método y algunas requieren expresiones lambda.However, certain queries can only be expressed in method syntax and some of those require lambda expressions. Cuando esté más familiarizado con las expresiones lambda, verá que se trata de una herramienta eficaz y flexible del cuadro de herramientas de LINQLINQ.After you become more familiar with lambdas, you will find that they are a powerful and flexible tool in your LINQLINQ toolbox. Para obtener más información, vea Expresiones lambda.For more information, see Lambda Expressions.

Capacidad de composición de consultasComposability of Queries

En el ejemplo de código anterior, tenga en cuenta que el método OrderBy se invoca mediante el operador de punto en la llamada a Where.In the previous code example, note that the OrderBy method is invoked by using the dot operator on the call to Where. Where crea una secuencia filtrada y, luego, Orderby actúa en dicha secuencia ordenándola.Where produces a filtered sequence, and then Orderby operates on that sequence by sorting it. Dado que las consultas devuelven un IEnumerable, redáctelas con la sintaxis de método encadenando las llamadas de método.Because queries return an IEnumerable, you compose them in method syntax by chaining the method calls together. Es lo que el compilador hace en segundo plano cuando se escriben consultas con la sintaxis de consulta.This is what the compiler does behind the scenes when you write queries by using query syntax. Y dado que una variable de consulta no almacena los resultados de la consulta, puede modificarla o usarla como base para una nueva consulta en cualquier momento, incluso después de que se haya ejecutado.And because a query variable does not store the results of the query, you can modify it or use it as the basis for a new query at any time, even after it has been executed.