from 句 (C# リファレンス)from clause (C# Reference)

クエリ式は、from 句で始める必要があります。A query expression must begin with a from clause. また、クエリ式にはサブクエリを含めることができます。サブクエリも from 句で始めます。Additionally, a query expression can contain sub-queries, which also begin with a from clause. from 句は次を指定します。The from clause specifies the following:

  • クエリまたはサブクエリを実行するデータ ソース。The data source on which the query or sub-query will be run.

  • ソース シーケンスの各要素を表す、ローカルの範囲変数A local range variable that represents each element in the source sequence.

範囲変数とデータ ソースの両方は厳密に型指定されます。Both the range variable and the data source are strongly typed. from 句で参照されるデータ ソースには、IEnumerable 型、IEnumerable<T> 型、あるいは 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>.

次の例では、numbers はデータ ソースであり、num は範囲変数です。In the following example, numbers is the data source and num is the range variable. 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

範囲変数The range variable

データ ソースが IEnumerable<T> を実装するとき、コンパイラは範囲変数の型を推測します。The compiler infers the type of the range variable when the data source implements IEnumerable<T>. たとえば、ソースの型が IEnumerable<Customer> の場合、範囲変数は Customer ではないかと推測されます。For example, if the source has a type of IEnumerable<Customer>, then the range variable is inferred to be Customer. ソースが ArrayList のような非ジェネリック IEnumerable 型のときにのみ、型を明示的に指定する必要があります。The only time that you must specify the type explicitly is when the source is a non-generic IEnumerable type such as ArrayList. 詳細については、「方法 :LINQ を使用して ArrayList を照会する」をご覧ください。For more information, see How to: Query an ArrayList with LINQ.

前述の例では、num は型 int として推測されます。In the previous example num is inferred to be of type int. 範囲変数は厳密に型指定されるため、範囲変数の上でメソッドを呼び出したり、他の操作で範囲変数を使用したりできます。Because the range variable is strongly typed, you can call methods on it or use it in other operations. たとえば、select num を記述する代わりに、select num.ToString() を記述し、クエリ式が整数ではなく文字列のシーケンスを返すようにできます。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. あるいは、式でシーケンス 14、11、13、12、10 を返すように select num + 10 を記述できます。Or you could write select num + 10 to cause the expression to return the sequence 14, 11, 13, 12, 10. 詳細については、「select 句」をご覧ください。For more information, see select clause.

範囲変数は foreach ステートメントの繰り返し変数に似ていますが、1 つだけ非常に重要な違いがあります。範囲変数がソースのデータを格納することは決してありません。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. これは構文上の利便性のためです。クエリの実行時に何が起こるのかクエリで表現できます。It's just a syntactic convenience that enables the query to describe what will occur when the query is executed. 詳細については、「LINQ クエリの概要 (C#)」を参照してください。For more information, see Introduction to LINQ Queries (C#).

複合 from 句Compound from clauses

ソース シーケンスの各要素がそれ自体シーケンスになったり、それ自体にシーケンスが含まれたりすることがあります。In some cases, each element in the source sequence may itself be either a sequence or contain a sequence. たとえば、データ ソースが IEnumerable<Student> になることがあります。この場合、シーケンスの各学生オブジェクト参照にテストの点数の一覧が含まれます。For example, your data source may be an IEnumerable<Student> where each student object in the sequence contains a list of test scores. Student 要素内の内部一覧にアクセスするには、複合 from 句を利用できます。To access the inner list within each Student element, you can use compound from clauses. この手法は、foreach ステートメントを入れ子にして使う場合に似ています。The technique is like using nested foreach statements. where 句または orderby 句をいずれかの from 句に追加し、結果を絞り込むことができます。You can add where or orderby clauses to either from clause to filter the results. 次は、Student オブジェクトのシーケンスの例です。テストの点数を表す整数の内部 List がそれぞれに含まれています。The following example shows a sequence of Student objects, each of which contains an inner List of integers representing test scores. 内部一覧にアクセスするには、複合 from 句を利用できます。To access the inner list, use a compound from clause. 必要に応じて、2 つの 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
*/

複数の from 句を使用して結合を実行するUsing Multiple from Clauses to Perform Joins

複合 from 句を使用し、単一データ ソースの内部コレクションにアクセスします。A compound from clause is used to access inner collections in a single data source. ただし、個別データ ソースから補足クエリを生成する複数の from 句をクエリに含めることもできます。However, a query can also contain multiple from clauses that generate supplemental queries from independent data sources. この手法では、join 句で不可能な特定の結合操作を実行できます。This technique enables you to perform certain types of join operations that are not possible by using the join clause.

2 つの from 句を使用し、2 つのデータ ソースの完全なクロス結合を作る様子を示したのが次の例です。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
        */

複数の from 句を使用する結合操作の詳細については、「左外部結合の実行」を参照してください。For more information about join operations that use multiple from clauses, see Perform left outer joins.

関連項目See also