select 절(C# 참조)

쿼리 식에서 select 절은 쿼리를 실행할 때 생성되는 값의 형식을 지정합니다. 결과는 모든 이전 절의 평가와 select 절 자체의 모든 계산을 기반으로 합니다. 쿼리 식은 select 절이나 group 절로 끝나야 합니다.

다음 예제에서는 쿼리 식의 간단한 select 절을 보여 줍니다.

class SelectSample1
{
    static void Main()
    {
        //Create the data source
        List<int> Scores = [97, 92, 81, 60];

        // Create the query.
        IEnumerable<int> queryHighScores =
            from score in Scores
            where score > 80
            select score;

        // Execute the query.
        foreach (int i in queryHighScores)
        {
            Console.Write(i + " ");
        }
    }
}
//Output: 97 92 81

select 절에서 생성된 시퀀스의 형식에 따라 쿼리 변수 queryHighScores의 형식이 결정됩니다. 가장 단순한 경우에서는 select 절이 범위 변수를 지정합니다. 이렇게 하면 반환된 시퀀스에 데이터 소스와 동일한 형식의 요소가 포함됩니다. 자세한 내용은 LINQ 쿼리 작업의 형식 관계를 참조하세요. 그러나 select 절은 소스 데이터를 새 형식으로 변환(또는 프로젝션)하기 위한 강력한 메커니즘도 제공합니다. 자세한 내용은 LINQ를 통한 데이터 변환(C#)을 참조하세요.

예시

다음 예제에서는 select 절에 사용할 수 있는 모든 형식을 보여 줍니다. 각 쿼리에서 select 절과 쿼리 변수 형식(studentQuery1, studentQuery2 등) 간의 관계를 확인합니다.

class SelectSample2
{
    // Define some classes
    public class Student
    {
        public required string First { get; init; }
        public required string Last { get; init; }
        public required int ID { get; init; }
        public required List<int> Scores;
        public ContactInfo? GetContactInfo(SelectSample2 app, int id)
        {
            ContactInfo? cInfo =
                (from ci in app.contactList
                where ci.ID == id
                select ci)
                .FirstOrDefault();

            return cInfo;
        }

        public override string ToString() => $"{First} {Last}:{ID}";
    }

    public class ContactInfo
    {
        public required int ID { get; init; }
        public required string Email { get; init; }
        public required string Phone { get; init; }
        public override string ToString() => $"{Email},{Phone}";
    }

    public class ScoreInfo
    {
        public double Average { get; init; }
        public int ID { get; init; }
    }

    // The primary data source
    List<Student> students =
    [
         new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores= new List<int>() {97, 92, 81, 60}},
         new Student {First="Claire", Last="O'Donnell", ID=112, Scores= new List<int>() {75, 84, 91, 39}},
         new Student {First="Sven", Last="Mortensen", ID=113, Scores= new List<int>() {88, 94, 65, 91}},
         new Student {First="Cesar", Last="Garcia", ID=114, Scores= new List<int>() {97, 89, 85, 82}},
    ];

    // Separate data source for contact info.
    List<ContactInfo> contactList =
    [
        new ContactInfo {ID=111, Email="SvetlanO@Contoso.com", Phone="206-555-0108"},
        new ContactInfo {ID=112, Email="ClaireO@Contoso.com", Phone="206-555-0298"},
        new ContactInfo {ID=113, Email="SvenMort@Contoso.com", Phone="206-555-1130"},
        new ContactInfo {ID=114, Email="CesarGar@Contoso.com", Phone="206-555-0521"}
    ];

    static void Main(string[] args)
    {
        SelectSample2 app = new SelectSample2();

        // Produce a filtered sequence of unmodified Students.
        IEnumerable<Student> studentQuery1 =
            from student in app.students
            where student.ID > 111
            select student;

        Console.WriteLine("Query1: select range_variable");
        foreach (Student s in studentQuery1)
        {
            Console.WriteLine(s.ToString());
        }

        // Produce a filtered sequence of elements that contain
        // only one property of each Student.
        IEnumerable<String> studentQuery2 =
            from student in app.students
            where student.ID > 111
            select student.Last;

        Console.WriteLine("\r\n studentQuery2: select range_variable.Property");
        foreach (string s in studentQuery2)
        {
            Console.WriteLine(s);
        }

        // Produce a filtered sequence of objects created by
        // a method call on each Student.
        IEnumerable<ContactInfo> studentQuery3 =
            from student in app.students
            where student.ID > 111
            select student.GetContactInfo(app, student.ID);

        Console.WriteLine("\r\n studentQuery3: select range_variable.Method");
        foreach (ContactInfo ci in studentQuery3)
        {
            Console.WriteLine(ci.ToString());
        }

        // Produce a filtered sequence of ints from
        // the internal array inside each Student.
        IEnumerable<int> studentQuery4 =
            from student in app.students
            where student.ID > 111
            select student.Scores[0];

        Console.WriteLine("\r\n studentQuery4: select range_variable[index]");
        foreach (int i in studentQuery4)
        {
            Console.WriteLine("First score = {0}", i);
        }

        // Produce a filtered sequence of doubles
        // that are the result of an expression.
        IEnumerable<double> studentQuery5 =
            from student in app.students
            where student.ID > 111
            select student.Scores[0] * 1.1;

        Console.WriteLine("\r\n studentQuery5: select expression");
        foreach (double d in studentQuery5)
        {
            Console.WriteLine("Adjusted first score = {0}", d);
        }

        // Produce a filtered sequence of doubles that are
        // the result of a method call.
        IEnumerable<double> studentQuery6 =
            from student in app.students
            where student.ID > 111
            select student.Scores.Average();

        Console.WriteLine("\r\n studentQuery6: select expression2");
        foreach (double d in studentQuery6)
        {
            Console.WriteLine("Average = {0}", d);
        }

        // Produce a filtered sequence of anonymous types
        // that contain only two properties from each Student.
        var studentQuery7 =
            from student in app.students
            where student.ID > 111
            select new { student.First, student.Last };

        Console.WriteLine("\r\n studentQuery7: select new anonymous type");
        foreach (var item in studentQuery7)
        {
            Console.WriteLine("{0}, {1}", item.Last, item.First);
        }

        // Produce a filtered sequence of named objects that contain
        // a method return value and a property from each Student.
        // Use named types if you need to pass the query variable
        // across a method boundary.
        IEnumerable<ScoreInfo> studentQuery8 =
            from student in app.students
            where student.ID > 111
            select new ScoreInfo
            {
                Average = student.Scores.Average(),
                ID = student.ID
            };

        Console.WriteLine("\r\n studentQuery8: select new named type");
        foreach (ScoreInfo si in studentQuery8)
        {
            Console.WriteLine("ID = {0}, Average = {1}", si.ID, si.Average);
        }

        // Produce a filtered sequence of students who appear on a contact list
        // and whose average is greater than 85.
        IEnumerable<ContactInfo> studentQuery9 =
            from student in app.students
            where student.Scores.Average() > 85
            join ci in app.contactList on student.ID equals ci.ID
            select ci;

        Console.WriteLine("\r\n studentQuery9: select result of join clause");
        foreach (ContactInfo ci in studentQuery9)
        {
            Console.WriteLine("ID = {0}, Email = {1}", ci.ID, ci.Email);
        }
    }
}
/* Output
    Query1: select range_variable
    Claire O'Donnell:112
    Sven Mortensen:113
    Cesar Garcia:114

    studentQuery2: select range_variable.Property
    O'Donnell
    Mortensen
    Garcia

    studentQuery3: select range_variable.Method
    ClaireO@Contoso.com,206-555-0298
    SvenMort@Contoso.com,206-555-1130
    CesarGar@Contoso.com,206-555-0521

    studentQuery4: select range_variable[index]
    First score = 75
    First score = 88
    First score = 97

    studentQuery5: select expression
    Adjusted first score = 82.5
    Adjusted first score = 96.8
    Adjusted first score = 106.7

    studentQuery6: select expression2
    Average = 72.25
    Average = 84.5
    Average = 88.25

    studentQuery7: select new anonymous type
    O'Donnell, Claire
    Mortensen, Sven
    Garcia, Cesar

    studentQuery8: select new named type
    ID = 112, Average = 72.25
    ID = 113, Average = 84.5
    ID = 114, Average = 88.25

    studentQuery9: select result of join clause
    ID = 114, Email = CesarGar@Contoso.com
*/

앞의 예제에서 studentQuery8에 표시된 대로 반환된 시퀀스의 요소에 소스 요소의 속성 하위 집합만 포함하려는 경우도 있습니다. 반환된 시퀀스를 최대한 작게 유지하면 메모리 요구 사항을 줄이고 쿼리 실행 속도를 높일 수 있습니다. select 절에서 무명 형식을 만들고 개체 이니셜라이저를 사용하여 소스 요소의 적절한 속성으로 초기화하면 됩니다. 이 작업을 수행하는 방법의 예를 보려면 개체 및 컬렉션 이니셜라이저를 참조하세요.

설명

컴파일 시간에 select 절은 Select 표준 쿼리 연산자에 대한 메서드 호출로 변환됩니다.

참고 항목