Clausola from (Riferimento C#)from clause (C# Reference)

Un'espressione di query deve iniziare con una clausola from.A query expression must begin with a from clause. Inoltre, un'espressione di query può contenere sottoquery che iniziano anch'esse con una clausola from.Additionally, a query expression can contain sub-queries, which also begin with a from clause. La clausola from specifica gli elementi seguenti:The from clause specifies the following:

  • Origine dati su cui verrà eseguita la query o la sottoquery.The data source on which the query or sub-query will be run.

  • Variabile di intervallo locale che rappresenta ogni elemento nella sequenza di origine.A local range variable that represents each element in the source sequence.

Sia la variabile di intervallo che l'origine dati sono fortemente tipizzate.Both the range variable and the data source are strongly typed. L'origine dati a cui si fa riferimento nella clausola from deve essere di tipo IEnumerable, IEnumerable<T> o di un tipo derivato, IQueryable<T>.The data source referenced in the from clause must have a type of IEnumerable, IEnumerable<T>, or a derived type such as IQueryable<T>.

Nell'esempio seguente numbers è l'origine dati e num è la variabile di intervallo.In the following example, numbers is the data source and num is the range variable. Si noti che entrambe le variabili sono fortemente tipizzate anche se viene usata la parola chiave var.Note that both variables are strongly typed even though the var keyword is used.

class LowNums
{
    static void Main()
    {   
        // A simple data source.
        int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

        // Create the query.
        // lowNums is an IEnumerable<int>
        var lowNums = from num in numbers
            where num < 5
            select num;

        // Execute the query.
        foreach (int i in lowNums)
        {
            Console.Write(i + " ");
        }
    }        
}
// Output: 4 1 3 2 0

Variabile di intervalloThe range variable

Tramite l'inferenza, il compilatore deriva il tipo della variabile di intervallo quando l'origine dati implementa IEnumerable<T>.The compiler infers the type of the range variable when the data source implements IEnumerable<T>. Se, ad esempio, l'origine è di tipo IEnumerable<Customer>, la variabile di intervallo derivata tramite inferenza sarà Customer.For example, if the source has a type of IEnumerable<Customer>, then the range variable is inferred to be Customer. È necessario specificare il tipo in modo esplicito solo quando l'origine è un tipo IEnumerable non generico, ad esempio ArrayList.The only time that you must specify the type explicitly is when the source is a non-generic IEnumerable type such as ArrayList. Per altre informazioni, vedere Procedura: Eseguire una query su un ArrayList con LINQ.For more information, see How to: Query an ArrayList with LINQ.

Nell'esempio precedente si deriva tramite inferenza che num è di tipo int.In the previous example num is inferred to be of type int. Poiché la variabile di intervallo è fortemente tipizzata, è possibile chiamare metodi su di essa o usarla in altre operazioni.Because the range variable is strongly typed, you can call methods on it or use it in other operations. Ad esempio, invece di scrivere select num, è possibile scrivere select num.ToString() per fare in modo che l'espressione di query restituisca una sequenza di stringhe invece che di numeri interi.For example, instead of writing select num, you could write select num.ToString() to cause the query expression to return a sequence of strings instead of integers. Oppure è possibile scrivere select num + 10 per fare in modo che l'espressione restituisca la sequenza 14, 11, 13, 12 10.Or you could write select num + 10 to cause the expression to return the sequence 14, 11, 13, 12, 10. Per altre informazioni, vedere Clausola select.For more information, see select clause.

La variabile di intervallo è analoga a una variabile di iterazione in un'istruzione foreach eccetto che per una differenza molto importante: una variabile di intervallo non archivia effettivamente mai i dati dall'origine.The range variable is like an iteration variable in a foreach statement except for one very important difference: a range variable never actually stores data from the source. Si tratta semplicemente di un pratico aspetto sintattico che consente alla query di descrivere ciò che si verificherà alla sua esecuzione.It's just a syntactic convenience that enables the query to describe what will occur when the query is executed. Per altre informazioni, vedere Introduzione alle query LINQ (C#).For more information, see Introduction to LINQ Queries (C#).

Clausole from composteCompound from clauses

In alcuni casi, ogni elemento nella sequenza di origine può essere esso stesso una sequenza o contenere una sequenza.In some cases, each element in the source sequence may itself be either a sequence or contain a sequence. Ad esempio, l'origine dati può essere un oggetto IEnumerable<Student> in cui ogni oggetto studente della sequenza contiene un elenco di punteggi dei test.For example, your data source may be an IEnumerable<Student> where each student object in the sequence contains a list of test scores. Per accedere all'elenco interno in ogni elemento Student è possibile usare clausole from composte.To access the inner list within each Student element, you can use compound from clauses. La tecnica è analoga all'uso di istruzioni foreach nidificate.The technique is like using nested foreach statements. È possibile aggiungere clausole where o orderby a una delle due clausole from per filtrare i risultati.You can add where or orderby clauses to either from clause to filter the results. L'esempio seguente mostra una sequenza di oggetti Student, ognuno dei quali contiene un oggetto List interno di numeri interi che rappresentano i punteggi dei test.The following example shows a sequence of Student objects, each of which contains an inner List of integers representing test scores. Per accedere all'elenco interno, usare una clausola from composta.To access the inner list, use a compound from clause. Se necessario, è possibile inserire clausole tra le due clausole from.You can insert clauses between the two from clauses if necessary.

class CompoundFrom
{
    // The element type of the data source.
    public class Student
    {
        public string LastName { get; set; }
        public List<int> Scores {get; set;}
    }

    static void Main()
    {
        
        // Use a collection initializer to create the data source. Note that 
        // each element in the list contains an inner sequence of scores.
        List<Student> students = new List<Student>
        {
           new Student {LastName="Omelchenko", Scores= new List<int> {97, 72, 81, 60}},
           new Student {LastName="O'Donnell", Scores= new List<int> {75, 84, 91, 39}},
           new Student {LastName="Mortensen", Scores= new List<int> {88, 94, 65, 85}},
           new Student {LastName="Garcia", Scores= new List<int> {97, 89, 85, 82}},
           new Student {LastName="Beebe", Scores= new List<int> {35, 72, 91, 70}} 
        };        

        // Use a compound from to access the inner sequence within each element.
        // Note the similarity to a nested foreach statement.
        var scoreQuery = from student in students
                         from score in student.Scores
                            where score > 90
                            select new { Last = student.LastName, score };
                    
        // Execute the queries.
        Console.WriteLine("scoreQuery:");
        // Rest the mouse pointer on scoreQuery in the following line to 
        // see its type. The type is IEnumerable<'a>, where 'a is an 
        // anonymous type defined as new {string Last, int score}. That is,
        // each instance of this anonymous type has two members, a string 
        // (Last) and an int (score).
        foreach (var student in scoreQuery)
        {
            Console.WriteLine("{0} Score: {1}", student.Last, student.score);
        }
        
        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }       
}
/*
scoreQuery:
Omelchenko Score: 97
O'Donnell Score: 91
Mortensen Score: 94
Garcia Score: 97
Beebe Score: 91
*/

Uso di più clausole from per eseguire joinUsing Multiple from Clauses to Perform Joins

Una clausola from composta viene usata per accedere a raccolte interne in una singola origine dati.A compound from clause is used to access inner collections in a single data source. Una query può tuttavia contenere anche più clausole from che generano query supplementari da origini dati indipendenti.However, a query can also contain multiple from clauses that generate supplemental queries from independent data sources. Questa tecnica consente di eseguire determinati tipi di operazioni di join che non sono possibili usando la clausola join.This technique enables you to perform certain types of join operations that are not possible by using the join clause.

L'esempio seguente mostra in che modo due clausole from possono essere usate per formare un cross join completo di due origini dati.The following example shows how two from clauses can be used to form a complete cross join of two data sources.

class CompoundFrom2
{
    static void Main()
    {
        char[] upperCase = { 'A', 'B', 'C' };
        char[] lowerCase = { 'x', 'y', 'z' };

        // The type of joinQuery1 is IEnumerable<'a>, where 'a
        // indicates an anonymous type. This anonymous type has two
        // members, upper and lower, both of type char.
        var joinQuery1 =
            from upper in upperCase
            from lower in lowerCase
            select new { upper, lower };

        // The type of joinQuery2 is IEnumerable<'a>, where 'a
        // indicates an anonymous type. This anonymous type has two
        // members, upper and lower, both of type char.
        var joinQuery2 =
            from lower in lowerCase
            where lower != 'x'
            from upper in upperCase
            select new { lower, upper };


        // Execute the queries.
        Console.WriteLine("Cross join:");
        // Rest the mouse pointer on joinQuery1 to verify its type.
        foreach (var pair in joinQuery1)
        {
            Console.WriteLine("{0} is matched to {1}", pair.upper, pair.lower);
        }

        Console.WriteLine("Filtered non-equijoin:");
        // Rest the mouse pointer over joinQuery2 to verify its type.
        foreach (var pair in joinQuery2)
        {
            Console.WriteLine("{0} is matched to {1}", pair.lower, pair.upper);
        }

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Output:
        Cross join:
        A is matched to x
        A is matched to y
        A is matched to z
        B is matched to x
        B is matched to y
        B is matched to z
        C is matched to x
        C is matched to y
        C is matched to z
        Filtered non-equijoin:
        y is matched to A
        y is matched to B
        y is matched to C
        z is matched to A
        z is matched to B
        z is matched to C
        */

Per altre informazioni sulle operazioni di join che usano più clausole from, vedere Eseguire left outer join.For more information about join operations that use multiple from clauses, see Perform left outer joins.

Vedere ancheSee also