Partilhar via


da cláusula (Referência C#)

Uma expressão de consulta deve começar com uma from cláusula. Além disso, uma expressão de consulta pode conter subconsultas, que também começam com uma from cláusula. A from cláusula especifica o seguinte:

  • A fonte de dados na qual a consulta ou subconsulta será executada.

  • Uma variável de intervalo local que representa cada elemento na sequência de origem.

Tanto a variável de intervalo quanto a fonte de dados são fortemente tipadas. A fonte de dados referenciada from na cláusula deve ter um tipo de IEnumerable, IEnumerable<T>ou um tipo derivado, como IQueryable<T>.

No exemplo a seguir, numbers é a fonte de dados e num é a variável de intervalo. Observe que ambas as variáveis são fortemente tipadas, mesmo que a palavra-chave var seja usada.

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

A variável de intervalo

O compilador infere o tipo da variável range quando a fonte de dados implementa IEnumerable<T>o . Por exemplo, se a fonte tiver um tipo de IEnumerable<Customer>, então a variável de intervalo é inferida como Customer. O único momento em que você deve especificar o tipo explicitamente é quando a origem é um tipo não genérico IEnumerable , como ArrayList. Para obter mais informações, consulte Como consultar uma ArrayList com LINQ.

No exemplo num anterior infere-se ser do tipo int. Como a variável range é fortemente tipada, você pode chamar métodos nela ou usá-la em outras operações. Por exemplo, em vez de escrever select num, você pode gravar select num.ToString() para fazer com que a expressão de consulta retorne uma sequência de cadeias de caracteres em vez de inteiros. Ou você pode escrever select num + 10 para fazer com que a expressão retorne a sequência 14, 11, 13, 12, 10. Para obter mais informações, consulte a cláusula select.

A variável range é como uma variável de iteração em uma instrução foreach, exceto por uma diferença muito importante: uma variável range nunca armazena dados da fonte. É apenas uma conveniência sintática que permite que a consulta descreva o que ocorrerá quando a consulta for executada. Para obter mais informações, consulte Introdução às consultas LINQ (C#).

Composto a partir de cláusulas

Em alguns casos, cada elemento na sequência de origem pode ser uma sequência ou conter uma sequência. Por exemplo, sua fonte de dados pode ser um IEnumerable<Student> em que cada objeto do aluno na sequência contém uma lista de pontuações de teste. Para acessar a lista interna dentro de cada Student elemento, você pode usar cláusulas compostas from . A técnica é como usar instruções foreach aninhadas. Você pode adicionar cláusulas where ou orderby a qualquer uma das from cláusulas para filtrar os resultados. O exemplo a seguir mostra uma sequência de Student objetos, cada um dos quais contém um interno List de inteiros que representam pontuações de teste. Para acessar a lista interna, use uma cláusula composta from . Se necessário, pode inserir cláusulas entre as duas from cláusulas.

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

    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 Student {LastName="Omelchenko", Scores= [97, 72, 81, 60]},
           new Student {LastName="O'Donnell", Scores= [75, 84, 91, 39]},
           new Student {LastName="Mortensen", Scores= [88, 94, 65, 85]},
           new Student {LastName="Garcia", Scores= [97, 89, 85, 82]},
           new Student {LastName="Beebe", Scores= [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);
        }
    }
}
/*
scoreQuery:
Omelchenko Score: 97
O'Donnell Score: 91
Mortensen Score: 94
Garcia Score: 97
Beebe Score: 91
*/

Usando várias cláusulas de várias para executar junções

Uma cláusula composta from é usada para acessar coleções internas em uma única fonte de dados. No entanto, uma consulta também pode conter várias from cláusulas que geram consultas suplementares de fontes de dados independentes. Essa técnica permite que você execute certos tipos de operações de junção que não são possíveis usando a cláusula de junção.

O exemplo a seguir mostra como duas from cláusulas podem ser usadas para formar uma junção cruzada completa de duas fontes de dados.

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
        */

Para obter mais informações sobre operações de junção que usam várias from cláusulas, consulte Executar junções externas à esquerda.

Consulte também