쿼리 작업의 형식 관계(Visual Basic)
LINQ(Language-Integrated Query) 쿼리 작업에 사용되는 변수는 강력한 형식이며 서로 호환되어야 합니다. 강력한 유형 지정은 데이터 원본, 쿼리 자체 및 쿼리 실행에서 사용됩니다. 다음 그림에서는 LINQ 쿼리를 설명하는 데 사용되는 용어를 식별합니다. 쿼리 부분에 대한 자세한 내용은 기본 쿼리 작업(Visual Basic)을 참조하세요.
쿼리의 범위 변수 형식은 데이터 원본의 요소 형식과 호환되어야 합니다. 쿼리 변수의 형식은 Select
절에 정의된 시퀀스 요소와 호환되어야 합니다. 마지막으로 시퀀스 요소의 형식도 쿼리를 실행하는 For Each
문에 사용되는 루프 제어 변수의 형식과 호환되어야 합니다. 이러한 강력한 형식 지정을 통해 컴파일 시 형식 오류를 쉽게 식별할 수 있습니다.
Visual Basic에서는 암시적 형식 지정이라고도 알려진 지역 형식 유추를 구현하여 강력한 형식 지정을 편리하게 만듭니다. 해당 기능은 이전 예에서 사용되었으며 LINQ 샘플 및 설명서 전체에서 사용되는 것을 볼 수 있습니다. Visual Basic에서는 As
절 없이 Dim
문을 사용하여 지역 형식 유추를 수행합니다. 다음 예에서 city
는 문자열로 강력하게 형식이 지정됩니다.
Dim city = "Seattle"
참고 항목
지역 형식 유추는 Option Infer
가 On
으로 설정된 경우에만 작동합니다. 자세한 내용은 Option Infer 문을 참조하세요.
그러나 쿼리에서 지역 형식 유추를 사용하더라도 데이터 원본의 변수, 쿼리 변수 및 쿼리 실행 루프 간에는 동일한 형식 관계가 존재합니다. LINQ 쿼리를 작성하거나 설명서의 샘플 및 코드 예를 사용할 때 이러한 형식 관계를 기본적으로 이해하는 것이 유용합니다.
데이터 원본에서 반환된 형식과 일치하지 않는 범위 변수에 대해 명시적인 형식을 지정해야 할 수도 있습니다. As
절을 사용하여 범위 변수의 형식을 지정할 수 있습니다. 그러나 변환이 축소 변환이고 Option Strict
가 On
으로 설정된 경우 오류가 발생합니다. 따라서 데이터 원본에서 검색된 값에 대해 변환을 수행하는 것이 좋습니다. 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
형식이 암시적으로 또는 명시적으로 결정되는지 여부에 관계없이 이전 코드 예 모두에는 다음 관계가 존재합니다.
데이터 원본
names
에 있는 요소 형식은 쿼리에 있는 범위 변수name
의 형식입니다.선택된 개체의 형식
name
에 따라 쿼리 변수의 형식mNames
가 결정됩니다. 여기서name
은 문자열이므로 Visual Basic에서 쿼리 변수는 IEnumerable(Of String)입니다.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
변수 간의 관계는 더 간단한 예의 관계와 같습니다.
데이터 원본
customers
에 있는 요소 형식은 쿼리에 있는 범위 변수cust
의 형식입니다. 이 예에서 해당 형식은Customer
입니다.Select
문은 전체 개체 대신 각Customer
개체의Name
속성을 반환합니다.Name
은 문자열이므로 쿼리 변수custNames
는 다시Customer
가 아닌 IEnumerable(Of String)이 됩니다.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
개체의 두 가지 속성인 Name
및 City
를 반환합니다. 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
이전 예에서 모든 변수에 대해 형식을 지정할 수는 없지만 관계는 동일하게 유지됩니다.
데이터 원본의 요소 형식은 다시 쿼리의 범위 변수 형식입니다. 이 예에서
cust
의 인스턴스가Customer
합니다.Select
문은 무명 형식을 생성하므로 쿼리 변수nameCityQuery
는 암시적으로 무명 형식으로 형식화되어야 합니다. 무명 형식에는 사용 가능한 이름이 없으므로 명시적으로 지정할 수 없습니다.For Each
루프의 반복 변수 형식은 2단계에서 만들어진 무명 형식입니다. 형식에 사용 가능한 이름이 없으므로 루프 반복 변수의 형식을 암시적으로 결정해야 합니다.
참고 항목
.NET