Sintassi di query e sintassi di metodi in LINQ (C#)Query Syntax and Method Syntax in LINQ (C#)

La maggior parte delle query nella documentazione di LINQ (Language Integrated Query) introduttiva viene scritta usando la sintassi di query dichiarativa LINQ.Most queries in the introductory Language Integrated Query (LINQ) documentation are written by using the LINQ declarative query syntax. Tuttavia, la sintassi di query deve essere convertita in chiamate al metodo per Common Language Runtime (CLR) di .NET quando il codice viene compilato.However, the query syntax must be translated into method calls for the .NET common language runtime (CLR) when the code is compiled. Queste chiamate al metodo richiamano gli operatori query standard, che hanno nomi come Where, Select, GroupBy, Join, Max e Average.These method calls invoke the standard query operators, which have names such as Where, Select, GroupBy, Join, Max, and Average. È possibile chiamarli direttamente usando la sintassi di metodo anziché la sintassi di query.You can call them directly by using method syntax instead of query syntax.

La sintassi di query e la sintassi di metodo sono semanticamente identiche, ma molti utenti ritengono che la sintassi di query sia più semplice e più facile da leggere.Query syntax and method syntax are semantically identical, but many people find query syntax simpler and easier to read. Alcune query devono essere espresse come chiamate al metodo.Some queries must be expressed as method calls. Ad esempio, è necessario usare una chiamata al metodo per esprimere una query che recupera il numero di elementi che soddisfano una determinata condizione.For example, you must use a method call to express a query that retrieves the number of elements that match a specified condition. È necessario usare una chiamata al metodo anche per una query che recupera l'elemento con il valore massimo in una sequenza di origine.You also must use a method call for a query that retrieves the element that has the maximum value in a source sequence. Nella documentazione di riferimento per gli operatori query standard nello spazio dei nomi System.Linq viene usata in genere la sintassi di metodo.The reference documentation for the standard query operators in the System.Linq namespace generally uses method syntax. Pertanto, anche quando si inizia a scrivere query LINQ, è utile acquisire familiarità con l'uso della sintassi del metodo nelle query e nelle espressioni di query.Therefore, even when getting started writing LINQ queries, it is useful to be familiar with how to use method syntax in queries and in query expressions themselves.

Metodi di estensione degli operatori query standardStandard Query Operator Extension Methods

Nell'esempio seguente viene illustrata un'espressione di query semplice e la query semanticamente equivalente scritta come query basata su metodo.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
 */

L'output dei due esempi è identico.The output from the two examples is identical. Si noterà che il tipo della variabile di query è lo stesso in entrambi i formati: IEnumerable<T>.You can see that the type of the query variable is the same in both forms: IEnumerable<T>.

Per capire meglio la query basata su metodo, esaminiamola più da vicino.To understand the method-based query, let's examine it more closely. Sul lato destro dell'espressione, si può notare che la clausola where viene ora espressa come metodo di istanza per l'oggetto numbers che, come si ricorderà, ha un tipo di 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>. Chi ha familiarità con l'interfaccia generica IEnumerable<T> sa che non ha un metodo Where.If you are familiar with the generic IEnumerable<T> interface, you know that it does not have a Where method. Tuttavia, se si richiama l'elenco di completamento IntelliSense nell'IDE di Visual Studio, si vedrà non solo un metodo Where ma molti altri metodi, ad esempio Select, SelectMany, Join e 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. Sono tutti operatori di query standard.These are all the standard query operators.

Screenshot di tutti gli operatori query standard in Intellisense.

Sebbene possa sembrare che IEnumerable<T> sia stata ridefinita in modo da includere questi metodi aggiuntivi, di fatto non è così.Although it looks as if IEnumerable<T> has been redefined to include these additional methods, in fact this is not the case. Gli operatori di query standard vengono implementati come un nuovo tipo di metodo denominato metodo di estensione.The standard query operators are implemented as a new kind of method called extension methods. I metodi di estensione "estendono" un tipo esistente. Possono essere chiamati come se fossero metodi di istanza per il tipo.Extensions methods "extend" an existing type; they can be called as if they were instance methods on the type. Gli operatori di query standard estendono IEnumerable<T> e questo è il motivo per cui è possibile scrivere numbers.Where(...).The standard query operators extend IEnumerable<T> and that is why you can write numbers.Where(...).

Per iniziare a usare LINQ, è sufficiente conoscere i metodi di estensione per riportarli nell'ambito dell'applicazione usando le using direttive corrette.To get started using LINQ, 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. Dal punto di vista dell'applicazione, un metodo di estensione e un metodo di istanza normale sono la stessa cosa.From your application's point of view, an extension method and a regular instance method are the same.

Per altre informazioni sui metodi di estensione, vedere Metodi di estensione.For more information about extension methods, see Extension Methods. Per altre informazioni sugli operatori di query standard, vedere Panoramica degli operatori di query standard (C#).For more information about standard query operators, see Standard Query Operators Overview (C#). Alcuni provider LINQ, ad esempio LINQ to SQLLINQ to SQL e LINQ to XMLLINQ to XML , implementano i propri operatori di query standard e i metodi di estensione aggiuntivi per altri tipi oltre a IEnumerable<T> .Some LINQ 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>.

Espressioni lambdaLambda Expressions

Nell'esempio precedente, si può notare che l'espressione condizionale (num % 2 == 0) viene passata come argomento inline al metodo Where: Where(num => num % 2 == 0). Questa espressione inline è definita espressione 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. È un modo pratico per scrivere codice che altrimenti dovrebbe essere scritto in un formato più complesso come metodo anonimo, delegato generico o albero delle espressioni.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. In C# => è l'operatore lambda, che viene letto come "goes to".In C# => is the lambda operator, which is read as "goes to". L'elemento num a sinistra dell'operatore è la variabile di input che corrisponde a num nell'espressione di query.The num on the left of the operator is the input variable which corresponds to num in the query expression. Il compilatore è in grado di dedurre il tipo di num poiché sa che numbers è un tipo IEnumerable<T> generico.The compiler can infer the type of num because it knows that numbers is a generic IEnumerable<T> type. Il corpo dell'espressione lambda è identico all'espressione nella sintassi di query o in qualsiasi altra espressione o istruzione di C# e può includere chiamate al metodo e altra logica complessa.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. Il valore restituito è semplicemente il risultato dell'espressione.The "return value" is just the expression result.

Per iniziare a usare LINQ, non è necessario utilizzare le espressioni lambda in modo esteso.To get started using LINQ, you do not have to use lambdas extensively. Tuttavia, alcune query possono essere espresse solo nella sintassi di metodo e alcune di esse richiedono le espressioni lambda.However, certain queries can only be expressed in method syntax and some of those require lambda expressions. Una volta acquisita familiarità con le espressioni lambda, si noterà che si tratta di uno strumento potente e flessibile nella casella degli strumenti di LINQ.After you become more familiar with lambdas, you will find that they are a powerful and flexible tool in your LINQ toolbox. Per altre informazioni, vedere espressioni lambda.For more information, see Lambda Expressions.

Componibilità delle queryComposability of Queries

Nell'esempio di codice precedente il metodo OrderBy viene richiamato usando l'operatore punto nella chiamata 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 genera una sequenza filtrata e quindi Orderby agisce sulla sequenza ordinandola.Where produces a filtered sequence, and then Orderby operates on that sequence by sorting it. Poiché le query restituiscono un oggetto IEnumerable, è necessario comporle nella sintassi di metodo concatenando le chiamate al metodo.Because queries return an IEnumerable, you compose them in method syntax by chaining the method calls together. Questa è l'operazione che il compilatore esegue in background quando si scrivono le query usando la sintassi di query.This is what the compiler does behind the scenes when you write queries by using query syntax. E poiché una variabile di query non archivia i risultati della query, è possibile modificarla o usarla come base per una nuova query in qualsiasi momento, anche dopo che è stata eseguita.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.