from (Cláusula, Referencia de C#)from clause (C# Reference)

Una expresión de consulta debe comenzar con una cláusula from,A query expression must begin with a from clause. Además, una expresión de consulta puede contener subconsultas, que también comienzan con una cláusula from.Additionally, a query expression can contain sub-queries, which also begin with a from clause. La cláusula from especifica lo siguiente:The from clause specifies the following:

  • El origen de datos en el que se ejecutará la consulta o subconsulta.The data source on which the query or sub-query will be run.

  • Una variable de rango local que representa cada elemento de la secuencia de origen.A local range variable that represents each element in the source sequence.

Tanto la variable de rango como el origen de datos están fuertemente tipados.Both the range variable and the data source are strongly typed. El origen de datos al que se hace referencia en la cláusula from debe tener un tipo de IEnumerable, IEnumerable<T> o un tipo derivado como 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>.

En el ejemplo siguiente, numbers es el origen de datos y num es la variable de rango.In the following example, numbers is the data source and num is the range variable. Tenga en cuenta que ambas variables están fuertemente tipadas a pesar de que se usa la palabra clave var.Note that both variables are strongly typed even through 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

La variable de rangoThe Range Variable

El compilador deduce el tipo de la variable de rango cuando el origen de datos implementa IEnumerable<T>.The compiler infers the type of the range variable when the data source implements IEnumerable<T>. Por ejemplo, si el origen tiene un tipo de IEnumerable<Customer>, entonces se deduce que la variable de rango es Customer.For example, if the source has a type of IEnumerable<Customer>, then the range variable is inferred to be Customer. La única vez en que debe especificar el tipo explícitamente es cuando el origen es un tipo IEnumerable no genérico como ArrayList.The only time that you must specify the type explicitly is when the source is a non-generic IEnumerable type such as ArrayList. Para obtener más información, vea How to: Query an ArrayList with LINQ (Consultar un objeto ArrayList con LINQ).For more information, see How to: Query an ArrayList with LINQ.

En el ejemplo anterior, num se deduce que es de tipo int.In the previous example num is inferred to be of type int. Como la variable de rango está fuertemente tipada, puede llamar a los métodos en ella o usarla en otras operaciones.Because the range variable is strongly typed, you can call methods on it or use it in other operations. Por ejemplo, en lugar de escribir select num, podría escribir select num.ToString() para hacer que la expresión de consulta devuelva una secuencia de cadenas en lugar de enteros.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. O podría escribir select n + 10 para hacer que la expresión devuelva la secuencia 14, 11, 13, 12, 10.Or you could write select n + 10 to cause the expression to return the sequence 14, 11, 13, 12, 10. Para obtener más información, vea Cláusula select.For more information, see select clause.

La variable de rango es como una variable de iteración en una instrucción foreach excepto por una diferencia muy importante: una variable de rango realmente nunca almacena datos del origen.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. Es solo una comodidad sintáctica que permite a la consulta describir lo que ocurrirá cuando se ejecute la consulta.It just a syntactic convenience that enables the query to describe what will occur when the query is executed. Para obtener más información, vea Introduction to LINQ queries (C#) [Introducción a las consultas LINQ (C#)].For more information, see Introduction to LINQ Queries (C#).

Cláusulas From compuestasCompound from Clauses

En algunos casos, cada elemento de la secuencia de origen puede ser por sí mismo una secuencia o contener una.In some cases, each element in the source sequence may itself be either a sequence or contain a sequence. Por ejemplo, su origen de datos puede ser un IEnumerable<Student> donde cada objeto de estudiante en la secuencia contiene una lista de resultados de las pruebas.For example, your data source may be an IEnumerable<Student> where each student object in the sequence contains a list of test scores. Para tener acceso a la lista interna dentro de cada elemento Student, puede usar las cláusulas from compuestas.To access the inner list within each Student element, you can use compound from clauses. La técnica es como usar instrucciones foreach anidadas.The technique is like using nested foreach statements. Puede agregar cláusulas where u orderby a cualquier cláusula from para filtrar los resultados.You can add where or orderby clauses to either from clause to filter the results. En el ejemplo siguiente se muestra una secuencia de objetos Student, cada uno de los cuales contiene un List interno de enteros que representa los resultados de las pruebas.The following example shows a sequence of Student objects, each of which contains an inner List of integers representing test scores. Para tener acceso a la lista interna, use una cláusula from compuesta.To access the inner list, use a compound from clause. Puede insertar cláusulas entre las dos cláusulas from si es necesario.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
*/

Usar cláusulas From múltiples para realizar combinacionesUsing Multiple from Clauses to Perform Joins

Una cláusula from compuesta se usa para tener acceso a las colecciones internas en un origen de datos único.A compound from clause is used to access inner collections in a single data source. En cambio, una consulta también puede contener varias cláusulas from que generan consultas adicionales de orígenes de datos independientes.However, a query can also contain multiple from clauses that generate supplemental queries from independent data sources. Esta técnica le permite realizar determinados tipos de operaciones de combinación que no son posibles mediante la cláusula join.This technique enables you to perform certain types of join operations that are not possible by using the join clause.

En el siguiente ejemplo se muestra cómo pueden usarse dos cláusulas from para formar una combinación cruzada completa de dos orígenes de datos.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
        */

Para obtener información sobre las operaciones de combinación que usan cláusulas from múltiples, vea Cómo: Realizar operaciones de combinación personalizadas.For more information about join operations that use multiple from clauses, see How to: Perform Custom Join Operations.

Vea tambiénSee Also

Palabras clave para consultas (LINQ)Query Keywords (LINQ)
Expresiones de consulta LINQLINQ Query Expressions