다음을 통해 공유


LINQ 쿼리 작업의 형식 관계(C#)

쿼리를 효과적으로 작성하려면 전체 쿼리 작업의 변수 형식이 서로 어떻게 관련되는지 이해해야 합니다. 이러한 관계를 이해하면 설명서의 LINQ 샘플 및 코드 예제를 더 쉽게 이해할 수 있습니다. 또한 var를 사용하여 변수가 암시적으로 형식화될 때 어떤 일이 발생하는지 이해하게 됩니다.

LINQ 쿼리 작업은 데이터 원본, 쿼리 자체 및 쿼리 실행에 강력하게 입력됩니다. 쿼리의 변수 형식은 데이터 원본의 요소 형식 및 문의 반복 변수 foreach 형식과 호환되어야 합니다. 이 강한 타입은 사용자가 오류를 경험하기 전에 수정할 수 있도록, 형식 오류가 컴파일 시간에 포착되도록 보장합니다.

이러한 형식 관계를 보여주기 위해 다음 예제의 대부분은 모든 변수에 대해 명시적 입력을 사용합니다. 마지막 예제에서는 암시적 입력을 사용하는 var경우에도 동일한 원칙이 적용되는 방법을 보여 줍니다.

원본 데이터를 변환하지 않는 쿼리

다음 그림에서는 데이터에 대한 변환을 수행하지 않는 LINQ to Objects 쿼리 작업을 보여 줍니다. 원본은 문자열 시퀀스를 포함하고 쿼리 출력은 문자열 시퀀스이기도 합니다.

LINQ 쿼리의 데이터 형식 관계를 보여 주는 다이어그램

  1. 데이터 원본의 형식 인수는 범위 변수의 형식을 결정합니다.
  2. 선택한 개체의 형식에 따라 쿼리 변수의 형식이 결정됩니다. 문자열은 다음과 같습니다 name . 따라서 쿼리 변수는 .입니다 IEnumerable<string>.
  3. 쿼리 변수는 foreach 문장 안에서 반복 처리됩니다. 쿼리 변수는 문자열 시퀀스이므로 반복 변수도 문자열입니다.

원본 데이터를 변환하는 쿼리

다음 그림에서는 데이터에 대한 간단한 변환을 수행하는 LINQ to SQL 쿼리 작업을 보여 줍니다. 쿼리는 Customer 개체의 시퀀스를 입력으로 받아 결과에서 Name 속성만을 선택합니다. Name 문자열이므로 쿼리는 문자열 시퀀스를 출력으로 생성합니다.

데이터 형식을 변환하는 쿼리를 보여 주는 다이어그램

  1. 데이터 원본의 형식 인수는 범위 변수의 형식을 결정합니다.
  2. select 문은 전체 Name 개체 대신 Customer 속성을 반환합니다. Name이 문자열이므로 형식 인수 custNameQuerystring가 아니라 Customer입니다.
  3. custNameQuery가 문자열 시퀀스이므로, foreach 루프의 반복 변수도 string이어야 합니다.

다음 그림에서는 약간 더 복잡한 변환을 보여 줍니다. select 문장은 원래 Customer 객체의 두 멤버만 캡처하는 익명 형식을 반환합니다.

데이터 형식을 변환하는 더 복잡한 쿼리를 보여 주는 다이어그램

  1. 데이터 원본의 형식 인수는 항상 쿼리에서 범위 변수의 형식입니다.
  2. 문은 select 익명 형식을 생성하므로 쿼리 변수는 var을(를) 사용하여 암시적으로 형식화되어야 합니다.
  3. 쿼리 변수의 형식이 암시적이므로 루프의 반복 변수 foreach 도 암시적이어야 합니다.

컴파일러에서 형식 정보를 유추하도록 허용

쿼리 작업의 형식 관계를 이해해야 하지만 컴파일러가 모든 작업을 수행할 수 있도록 하는 옵션이 있습니다. 키워드 var 은 쿼리 작업의 모든 지역 변수에 사용할 수 있습니다. 다음 그림은 앞에서 설명한 예제 번호 2와 유사합니다. 그러나 컴파일러는 쿼리 작업의 각 변수에 강력한 형식을 제공합니다.

암시적 입력이 있는 형식 흐름을 보여 주는 다이어그램

LINQ 및 제네릭 형식(C#)

LINQ 쿼리는 제네릭 형식을 기반으로 합니다. 쿼리 작성을 시작하기 전에 제네릭에 대한 자세한 지식이 필요하지 않습니다. 그러나 다음 두 가지 기본 개념을 이해하려고 할 수 있습니다.

  1. 같은 List<T>제네릭 컬렉션 클래스의 인스턴스를 만들 때 "T"를 목록에 포함할 개체의 형식으로 바꿉니다. 예를 들어 문자열 목록은 로 List<string>표현되고 개체 목록은 Customer .로 List<Customer>표현됩니다. 제네릭 목록은 강력한 형식이며 요소를 다음과 같이 Object저장하는 컬렉션에 비해 많은 이점을 제공합니다. CustomerList<string>에 추가하려고 하면 컴파일 시 오류가 발생합니다. 런타임 형식 캐스팅을 수행할 필요가 없으므로 제네릭 컬렉션을 사용하기 쉽습니다.
  2. IEnumerable<T> 는 문을 사용하여 제네릭 컬렉션 클래스를 열거할 수 있도록 하는 인터페이스입니다 foreach . 제네릭 컬렉션 클래스는 IEnumerable<T>를 지원하며, 제네릭이 아닌 컬렉션 클래스들도 ArrayList을 지원하여 IEnumerable와 같은 방식으로 기능합니다.

제네릭에 대한 자세한 내용은 제네릭을 참조하세요.

LINQ 쿼리의 IEnumerable<T> 변수

LINQ 쿼리 변수는 IEnumerable<T> 또는 IQueryable<T>와 같은 파생 형식으로 유형 지정됩니다. 형식화된 IEnumerable<Customer>쿼리 변수가 표시되면 쿼리가 실행될 때 0개 이상의 Customer 개체 시퀀스를 생성한다는 의미일 뿐입니다.

IEnumerable<Customer> customerQuery = from cust in customers
                                      where cust.City == "London"
                                      select cust;

foreach (Customer customer in customerQuery)
{
    Console.WriteLine($"{customer.LastName}, {customer.FirstName}");
}

컴파일러에서 제네릭 형식 선언을 처리하도록 허용

원하는 경우 var 키워드를 사용하여 제네릭 구문을 방지할 수 있습니다. 이 키워드는 var 절에 지정된 데이터 원본을 확인하여 쿼리 변수의 형식을 유추하도록 컴파일러에 from 지시합니다. 다음 예제에서는 이전 예제와 동일한 컴파일된 코드를 생성합니다.

var customerQuery2 = from cust in customers
                     where cust.City == "London"
                     select cust;

foreach(var customer in customerQuery2)
{
    Console.WriteLine($"{customer.LastName}, {customer.FirstName}");
}

var 키워드는 변수의 형식이 명백하거나 그룹 쿼리에서 생성되는 형식과 같이 중첩된 제네릭 형식을 명시적으로 지정하는 것이 중요하지 않은 경우에 유용합니다. 일반적으로 사용하는 var경우 코드를 다른 사용자가 읽기 어렵게 만들 수 있음을 깨닫는 것이 좋습니다. 자세한 내용은 암시적으로 형식화된 지역 변수를 참조하세요.