from 절(C# 참조)

업데이트: 2007년 11월

쿼리 식은 from 절로 시작해야 합니다. 또한 쿼리 식은 마찬가지로 from 절로 시작하는 하위 쿼리를 포함할 수 있습니다. from 절은 다음을 지정합니다.

  • 쿼리 또는 하위 쿼리가 실행되는 데이터 소스

  • 소스 시퀀스의 각 요소를 나타내는 지역 범위 변수

범위 변수와 데이터 소스는 둘 다 강력한 형식입니다. from 절에서 참조되는 데이터 소스는 IEnumerable 또는 IEnumerable<T> 형식이나 IQueryable<T>과 같은 파생 형식이어야 합니다.

다음 예제에서 numbers는 데이터 소스이고 num은 범위 변수입니다. var 키워드가 사용되어도 두 변수는 모두 강력한 형식입니다.

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

범위 변수

컴파일러는 데이터 소스가 IEnumerable<T>을 구현할 경우 범위 변수의 형식을 유추합니다. 예를 들어, 소스의 형식이 **IEnumerable<Customer>**일 경우 범위 변수는 Customer로 유추됩니다. 소스가 ArrayList와 같은 제네릭이 아닌 IEnumerable 형식일 경우에만 형식을 명시적으로 지정하면 됩니다. 자세한 내용은 방법: LINQ를 사용하여 ArrayList 쿼리을를 참조하십시오.

위의 예제에서 num은 int 형식으로 유추됩니다. 범위 변수가 강력한 형식이므로 범위 변수에서 메서드를 호출하거나 다른 작업에서 범위 변수를 사용할 수 있습니다. 예를 들어, select num을 작성하는 대신에 select num.ToString()을 작성하여 쿼리 식에서 정수 대신 문자열 시퀀스를 반환하게 할 수 있습니다. 또는 select n + 10을 작성하여 식에서 14, 11, 13, 12, 10 시퀀스를 반환하게 할 수 있습니다. 자세한 내용은 select 절(C# 참조)을 참조하십시오.

범위 변수가 소스의 데이터를 실제로 저장하지 않는다는 매우 중요한 차이점을 제외하면 범위 변수는 foreach 문의 반복 변수와 같습니다. 범위 변수는 단순히 쿼리 실행 시에 발생하는 작업을 쿼리에서 설명할 수 있게 하는 구문상의 편리함을 제공합니다. 자세한 내용은 LINQ 쿼리 소개를 참조하십시오.

복합 from 절

경우에 따라 소스 시퀀스의 각 요소 자체가 시퀀스이거나 시퀀스를 포함할 수 있습니다. 예를 들어, 시퀀스의 각 학생 개체에 테스트 점수 목록이 포함된 **IEnumerable<Student>**가 데이터 소스일 수 있습니다. 각 Student 요소 내의 내부 목록에 액세스하려면 복합 from 절을 사용합니다. 이 기술은 중첩된 foreach 문을 사용하는 것과 같습니다. where 또는 orderby 절을 둘 중 하나의 from 절에 추가하여 결과를 필터링할 수 있습니다. 다음 예제에서는 테스트 점수를 나타내는 정수의 내부 List를 각각 포함하는 Student 개체의 시퀀스를 보여 줍니다. 내부 목록에 액세스하려면 복합 from 절을 사용합니다. 필요한 경우 두 개의 from 절 사이에 다른 절을 삽입할 수 있습니다.

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:");
        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 절을 사용하여 조인 수행

복합 from 절은 단일 데이터 소스의 내부 컬렉션에 액세스하는 데 사용됩니다. 그러나 독립 데이터 소스의 추가 쿼리를 생성하는 여러 from 절이 쿼리에 포함될 수도 있습니다. 이 기술을 사용하면 join 절로 수행할 수 없는 특정 유형의 조인 작업을 수행할 수 있습니다.

다음 예제에서는 두 개의 from 절을 사용하여 두 데이터 소스의 완전한 크로스 조인을 구성하는 방법을 보여 줍니다.

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

        var joinQuery1 =
            from upper in upperCase
            from lower in lowerCase
                select new { upper, lower};

        var joinQuery2 =
            from lower in lowerCase
            where lower != 'x'
            from upper in upperCase
            select new { lower, upper };


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

        Console.WriteLine("Filtered non-equijoin:");
        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 절을 사용하는 조인 작업에 대한 자세한 내용은 방법: 사용자 지정 조인 작업 수행(C# 프로그래밍 가이드)을 참조하십시오.

참고 항목

개념

LINQ 쿼리 식(C# 프로그래밍 가이드)

기타 리소스

쿼리 키워드(C# 참조)