다음을 통해 공유


쿼리 작업의 형식 관계(Visual Basic)

LINQ(Language-Integrated Query) 쿼리 작업에 사용되는 변수는 강력한 형식이며 서로 호환되어야 합니다. 강력한 유형 지정은 데이터 원본, 쿼리 자체 및 쿼리 실행에서 사용됩니다. 다음 그림에서는 LINQ 쿼리를 설명하는 데 사용되는 용어를 식별합니다. 쿼리 부분에 대한 자세한 내용은 기본 쿼리 작업(Visual Basic)을 참조하세요.

Screenshot showing a pseudocode query with elements highlighted.

쿼리의 범위 변수 형식은 데이터 원본의 요소 형식과 호환되어야 합니다. 쿼리 변수의 형식은 Select 절에 정의된 시퀀스 요소와 호환되어야 합니다. 마지막으로 시퀀스 요소의 형식도 쿼리를 실행하는 For Each 문에 사용되는 루프 제어 변수의 형식과 호환되어야 합니다. 이러한 강력한 형식 지정을 통해 컴파일 시 형식 오류를 쉽게 식별할 수 있습니다.

Visual Basic에서는 암시적 형식 지정이라고도 알려진 지역 형식 유추를 구현하여 강력한 형식 지정을 편리하게 만듭니다. 해당 기능은 이전 예에서 사용되었으며 LINQ 샘플 및 설명서 전체에서 사용되는 것을 볼 수 있습니다. Visual Basic에서는 As 절 없이 Dim 문을 사용하여 지역 형식 유추를 수행합니다. 다음 예에서 city는 문자열로 강력하게 형식이 지정됩니다.

Dim city = "Seattle"

참고 항목

지역 형식 유추는 Option InferOn으로 설정된 경우에만 작동합니다. 자세한 내용은 Option Infer 문을 참조하세요.

그러나 쿼리에서 지역 형식 유추를 사용하더라도 데이터 원본의 변수, 쿼리 변수 및 쿼리 실행 루프 간에는 동일한 형식 관계가 존재합니다. LINQ 쿼리를 작성하거나 설명서의 샘플 및 코드 예를 사용할 때 이러한 형식 관계를 기본적으로 이해하는 것이 유용합니다.

데이터 원본에서 반환된 형식과 일치하지 않는 범위 변수에 대해 명시적인 형식을 지정해야 할 수도 있습니다. As 절을 사용하여 범위 변수의 형식을 지정할 수 있습니다. 그러나 변환이 축소 변환이고 Option StrictOn으로 설정된 경우 오류가 발생합니다. 따라서 데이터 원본에서 검색된 값에 대해 변환을 수행하는 것이 좋습니다. Cast 메서드를 사용하여 데이터 원본의 값을 명시적 범위 변수 형식으로 변환할 수 있습니다. 또한 Select 절에서 선택한 값을 범위 변수 형식과 다른 명시적 형식으로 캐스팅할 수도 있습니다. 이러한 사항은 다음 코드에 설명되어 있습니다.

Dim numbers1() As Integer = {1, 2, 4, 16, 32, 64}
Dim numbers2() As Double = {5.0#, 10.0#, 15.0#}

' This code does not result in an error.
Dim numberQuery1 = From n As Integer In numbers1 Where n > 5

' This code results in an error with Option Strict set to On. The type Double
' cannot be implicitly cast as type Integer.
Dim numberQuery2 = From n As Integer In numbers2 Where n > 5

' This code casts the values in the data source to type Integer. The type of
' the range variable is Integer.
Dim numberQuery3 = From n In numbers2.Cast(Of Integer)() Where n > 5

' This code returns the value of the range variable converted to Integer. The type of
' the range variable is Double.
Dim numberQuery4 = From n In numbers2 Where n > 5 Select CInt(n)

원본 데이터의 전체 요소를 반환하는 쿼리

다음 예에서는 원본 데이터에서 선택한 요소의 시퀀스를 반환하는 LINQ 쿼리 작업을 보여 줍니다. 원본 names에는 문자열 배열이 포함되어 있고 쿼리 출력은 문자 M으로 시작하는 문자열이 포함된 시퀀스입니다.

Dim names = {"John", "Rick", "Maggie", "Mary"}
Dim mNames = From name In names
             Where name.IndexOf("M") = 0
             Select name

For Each nm In mNames
    Console.WriteLine(nm)
Next

이는 다음 코드와 동등하지만 훨씬 짧고 작성하기 쉽습니다. 쿼리에서 지역 형식 유추에 의존하는 것은 Visual Basic에서 기본 설정되는 스타일입니다.

Dim names2 = {"John", "Rick", "Maggie", "Mary"}
Dim mNames2 As IEnumerable(Of String) =
    From name As String In names
    Where name.IndexOf("M") = 0
    Select name

For Each nm As String In mNames
    Console.WriteLine(nm)
Next

형식이 암시적으로 또는 명시적으로 결정되는지 여부에 관계없이 이전 코드 예 모두에는 다음 관계가 존재합니다.

  1. 데이터 원본 names에 있는 요소 형식은 쿼리에 있는 범위 변수 name의 형식입니다.

  2. 선택된 개체의 형식 name에 따라 쿼리 변수의 형식 mNames가 결정됩니다. 여기서 name은 문자열이므로 Visual Basic에서 쿼리 변수는 IEnumerable(Of String)입니다.

  3. mNames에 정의된 쿼리는 For Each 루프에서 실행됩니다. 루프는 쿼리 실행 결과를 반복합니다. mNames가 실행되면 문자열 시퀀스를 반환하므로 루프 반복 변수 nm도 문자열입니다.

선택한 요소에서 하나의 필드를 반환하는 쿼리

다음 예에서는 데이터 원본에서 선택한 각 요소의 한 부분만 포함하는 시퀀스를 반환하는 LINQ to SQL 쿼리 작업을 보여 줍니다. 쿼리는 Customer 개체 컬렉션을 데이터 원본으로 사용하고 결과에 Name 속성만 투영합니다. 고객 이름은 문자열이므로 쿼리는 일련의 문자열을 출력으로 생성합니다.

' Method GetTable returns a table of Customer objects.
Dim customers = db.GetTable(Of Customer)()
Dim custNames = From cust In customers
                Where cust.City = "London"
                Select cust.Name

For Each custName In custNames
    Console.WriteLine(custName)
Next

변수 간의 관계는 더 간단한 예의 관계와 같습니다.

  1. 데이터 원본 customers에 있는 요소 형식은 쿼리에 있는 범위 변수 cust의 형식입니다. 이 예에서 해당 형식은 Customer입니다.

  2. Select 문은 전체 개체 대신 각 Customer 개체의 Name 속성을 반환합니다. Name은 문자열이므로 쿼리 변수 custNames는 다시 Customer가 아닌 IEnumerable(Of String)이 됩니다.

  3. custNames는 문자열 시퀀스를 나타내므로 For Each 루프의 반복 변수 custName은 문자열이어야 합니다.

지역 형식 유추가 없으면 다음 예에서 볼 수 있듯이 이전 예를 작성하고 이해하기가 더 복잡해집니다.

' Method GetTable returns a table of Customer objects.
 Dim customers As Table(Of Customer) = db.GetTable(Of Customer)()
 Dim custNames As IEnumerable(Of String) =
     From cust As Customer In customers
     Where cust.City = "London"
     Select cust.Name

 For Each custName As String In custNames
     Console.WriteLine(custName)
 Next

무명 형식이 필요한 쿼리

다음 예에서는 보다 복잡한 상황을 보여 줍니다. 이전 예에서는 모든 변수에 대해 명시적으로 형식을 지정하는 것이 불편했습니다. 이 예에서는 불가능합니다. 데이터 원본에서 전체 Customer 요소를 선택하거나 각 요소에서 단일 필드를 선택하는 대신 이 쿼리의 Select 절은 원래 Customer 개체의 두 가지 속성인 NameCity를 반환합니다. Select 절에 대한 응답으로 컴파일러는 이러한 두 속성을 포함하는 무명 형식을 정의합니다. For Each 루프에서 nameCityQuery를 실행한 결과는 새로운 무명 형식의 인스턴스 컬렉션입니다. 무명 형식에는 사용 가능한 이름이 없으므로 nameCityQuery 또는 custInfo 형식을 명시적으로 지정할 수 없습니다. 즉, 무명 형식의 경우 IEnumerable(Of String)String 대신 사용할 형식 이름이 없습니다. 자세한 내용은 무명 형식을 참조하세요.

' Method GetTable returns a table of Customer objects.
Dim customers = db.GetTable(Of Customer)()
Dim nameCityQuery = From cust In customers
                    Where cust.City = "London"
                    Select cust.Name, cust.City

For Each custInfo In nameCityQuery
    Console.WriteLine(custInfo.Name)
Next

이전 예에서 모든 변수에 대해 형식을 지정할 수는 없지만 관계는 동일하게 유지됩니다.

  1. 데이터 원본의 요소 형식은 다시 쿼리의 범위 변수 형식입니다. 이 예에서 cust 의 인스턴스가 Customer합니다.

  2. Select 문은 무명 형식을 생성하므로 쿼리 변수 nameCityQuery는 암시적으로 무명 형식으로 형식화되어야 합니다. 무명 형식에는 사용 가능한 이름이 없으므로 명시적으로 지정할 수 없습니다.

  3. For Each 루프의 반복 변수 형식은 2단계에서 만들어진 무명 형식입니다. 형식에 사용 가능한 이름이 없으므로 루프 반복 변수의 형식을 암시적으로 결정해야 합니다.

참고 항목