from-Klausel (C#-Referenz)from clause (C# Reference)

Ein Abfrageausdruck muss mit einer from-Klausel beginnen.A query expression must begin with a from clause. Darüber hinaus kann ein Abfrageausdruck Unterabfragen enthalten, die auch mit einer from-Klausel beginnen.Additionally, a query expression can contain sub-queries, which also begin with a from clause. Die from-Klausel gibt Folgendes an:The from clause specifies the following:

  • Die Datenquelle, für die die Abfrage oder Unterabfrage ausgeführt wird.The data source on which the query or sub-query will be run.

  • Eine lokale Bereichsvariable, die jedes Element in der Quellsequenz darstellt.A local range variable that represents each element in the source sequence.

Sowohl die Bereichsvariable als auch die Datenquelle sind stark typisiert.Both the range variable and the data source are strongly typed. Die Datenquelle, auf die in der from-Klausel verwiesen wird, muss vom Typ IEnumerable, IEnumerable<T> oder von einem abgeleiteten Typ wie IQueryable<T> sein.The data source referenced in the from clause must have a type of IEnumerable, IEnumerable<T>, or a derived type such as IQueryable<T>.

Im folgenden Beispiel numbers ist die Datenquelle und num ist die Bereichsvariable.In the following example, numbers is the data source and num is the range variable. Beachten Sie, dass beide Variablen stark typisiert sind, obwohl das var-Schlüsselwort verwendet wird.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

Die BereichsvariableThe range variable

Der Compiler leitet den Typ der Bereichsvariablen ab, wenn die Datenquelle IEnumerable<T> implementiert.The compiler infers the type of the range variable when the data source implements IEnumerable<T>. Wenn die Quelle beispielsweise vom Typ IEnumerable<Customer> ist, wird die Bereichsvariable als Customer abgeleitet.For example, if the source has a type of IEnumerable<Customer>, then the range variable is inferred to be Customer. Sie müssen den Typ nur explizit angeben, wenn die Quelle ein nicht-generischer IEnumerable-Typ wie z.B. ArrayList ist.The only time that you must specify the type explicitly is when the source is a non-generic IEnumerable type such as ArrayList. Weitere Informationen finden Sie unter How to: Query an ArrayList with LINQ (Vorgehensweise: Abfragen von ArrayList mit LINQ).For more information, see How to: Query an ArrayList with LINQ.

Im vorherigen Beispiel wird num als Typ int abgeleitet.In the previous example num is inferred to be of type int. Da die Bereichsvariable stark typisiert ist, können Sie für sie Methoden aufrufen oder sie in anderen Vorgängen verwenden.Because the range variable is strongly typed, you can call methods on it or use it in other operations. Anstatt z.B. select num zu schreiben, könnten Sie select num.ToString() schreiben, sodass der Abfrageausdruck eine Sequenz von Zeichenfolgen anstelle von Ganzzahlen zurückgibt.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. Sie könnten auch select n + 10 schreiben, damit der Ausdruck die Sequenz „14, 11, 13, 12, 10“ zurückgibt.Or you could write select n + 10 to cause the expression to return the sequence 14, 11, 13, 12, 10. Weitere Informationen finden Sie unter select clause (select-Klausel).For more information, see select clause.

Die Bereichsvariable entspricht einer Iterationsvariablen in einer foreach-Anweisung mit einer wichtigen Ausnahme: Eine Bereichsvariable speichert niemals Daten aus der Quelle.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. Sie ist nur ein syntaktisches Hilfsmittel, mit dem die Abfrage beschreiben kann, was eintritt, wenn die Abfrage ausgeführt wird.It just a syntactic convenience that enables the query to describe what will occur when the query is executed. Weitere Informationen finden Sie unter Introduction to LINQ queries (C#) (Einführung in LINQ-Abfragen (C#)).For more information, see Introduction to LINQ Queries (C#).

Zusammengesetzte from-KlauselnCompound from clauses

In einigen Fällen kann jedes Element in der Quellsequenz selbst eine Sequenz sein oder eine Sequenz enthalten.In some cases, each element in the source sequence may itself be either a sequence or contain a sequence. Ihre Datenquelle kann beispielsweise ein IEnumerable<Student> sein, wobei jedes Student-Objekt in der Sequenz eine Liste der Testergebnisse enthält.For example, your data source may be an IEnumerable<Student> where each student object in the sequence contains a list of test scores. Sie können zusammengesetzte from-Klauseln verwenden, um auf die innere Liste jedes Student-Objekts zuzugreifen.To access the inner list within each Student element, you can use compound from clauses. Die Technik entspricht dem Verwenden von geschachtelten foreach-Anweisungen.The technique is like using nested foreach statements. Sie können die where-Klausel oder die orderby-Klausel zu einer der from-Klauseln hinzufügen, um die Ergebnisse zu filtern.You can add where or orderby clauses to either from clause to filter the results. Das folgende Beispiel enthält eine Sequenz von Student-Objekten, von denen jedes eine innere List mit Ganzzahlen enthält, die die Testergebnisse darstellen.The following example shows a sequence of Student objects, each of which contains an inner List of integers representing test scores. Um auf die innere Liste zuzugreifen, verwenden Sie eine zusammengesetzte from-Klausel.To access the inner list, use a compound from clause. Bei Bedarf können Sie Klauseln zwischen den beiden from-Klauseln einfügen.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
*/

Verwenden von mehreren from-Klauseln zum Ausführen von JoinsUsing Multiple from Clauses to Perform Joins

Eine zusammengesetzte from-Klausel wird zum Zugriff auf innere Auflistungen in einer einzelnen Datenquelle verwendet.A compound from clause is used to access inner collections in a single data source. Eine Abfrage kann jedoch auch mehrere from-Klauseln enthalten, die ergänzende Abfragen aus unabhängigen Datenquellen generieren.However, a query can also contain multiple from clauses that generate supplemental queries from independent data sources. Mit dieser Technik können Sie bestimmte Typen von Verknüpfungsvorgängen durchführen, die beim Einsatz der join-Klausel nicht möglich sind.This technique enables you to perform certain types of join operations that are not possible by using the join clause.

Das folgende Beispiel veranschaulicht, wie zwei from-Klauseln verwendet werden können, um einen vollständigen Cross Join zweier Datenquellen zu bilden.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
        */

Weitere Informationen zu Verknüpfungsvorgängen mit mehreren from-Klauseln finden Sie unter Ausführen von Left Outer Joins.For more information about join operations that use multiple from clauses, see Perform left outer joins.

Siehe auchSee also

Abfrageschlüsselwörter (LINQ)Query Keywords (LINQ)
Language-Integrated Query (LINQ)Language Integrated Query (LINQ)