다음을 통해 공유


방법: LINQ 쿼리에 대한 사용자 지정 메서드 추가(Visual Basic)

인터페이스에 확장 메서드를 추가하여 LINQ 쿼리에 사용하는 메서드 집합을 IEnumerable<T> 확장합니다. 예를 들어 표준 평균 또는 최대 작업 외에도 값 시퀀스에서 단일 값을 계산하는 사용자 지정 집계 메서드를 만듭니다. 또한 값 시퀀스에 대한 사용자 지정 필터 또는 특정 데이터 변환으로 작동하고 새 시퀀스를 반환하는 메서드를 만듭니다. 이러한 메서드의 예는 Distinct, SkipReverse.

인터페이스를 IEnumerable<T> 확장할 때 열거 가능한 컬렉션에 사용자 지정 메서드를 적용할 수 있습니다. 자세한 내용은 확장 메서드를 참조하세요.

집계 메서드 추가

집계 메서드는 값 집합에서 단일 값을 계산합니다. LINQ는 , AverageMin.를 비롯한 Max여러 집계 메서드를 제공합니다. 인터페이스에 확장 메서드를 추가하여 고유한 집계 메서드를 IEnumerable<T> 만들 수 있습니다.

다음 코드 예제에서는 형식Median의 숫자 시퀀스에 대한 중앙값을 계산하기 위해 호출 double 되는 확장 메서드를 만드는 방법을 보여 줍니다.

Imports System.Runtime.CompilerServices

Module LINQExtension

    ' Extension method for the IEnumerable(of T) interface.
    ' The method accepts only values of the Double type.
    <Extension()>
    Function Median(ByVal source As IEnumerable(Of Double)) As Double
        If Not source.Any() Then
            Throw New InvalidOperationException("Cannot compute median for an empty set.")
        End If

        Dim sortedSource = (From number In source
                            Order By number).ToList()

        Dim itemIndex = sortedSource.Count \ 2

        If sortedSource.Count Mod 2 = 0 Then
            ' Even number of items in list.
            Return (sortedSource(itemIndex) + sortedSource(itemIndex - 1)) / 2
        Else
            ' Odd number of items in list.
            Return sortedSource(itemIndex)
        End If
    End Function
End Module

인터페이스에서 다른 집계 메서드를 호출하는 것과 동일한 방식으로 열거 가능한 컬렉션에 대해 이 확장 메서드를 IEnumerable<T> 호출합니다.

비고

Visual Basic에서는 Aggregate 절 또는 Group By 절에 대해 메서드 호출이나 표준 쿼리 구문을 사용할 수 있습니다. 자세한 내용은 집계 절그룹 기준 절를 참조하세요.

다음 코드 예제에서는 형식Median의 배열에 메서드를 사용 double 하는 방법을 보여 있습니다.

Dim numbers() As Double = {1.9, 2, 8, 4, 5.7, 6, 7.2, 0}

Dim query = Aggregate num In numbers Into Median()

Console.WriteLine("Double: Median = " & query)
' This code produces the following output:
'
' Double: Median = 4.85

다양한 형식을 허용하기 위해 집계 메서드를 오버로드하기

다양한 형식의 시퀀스를 허용하도록 집계 메서드를 오버로드할 수 있습니다. 표준 방법은 각 형식에 대한 오버로드를 만드는 것입니다. 또 다른 방법은 제네릭 형식을 사용하고 대리자를 사용하여 특정 형식으로 변환하는 오버로드를 만드는 것입니다. 두 방법을 모두 결합할 수도 있습니다.

각 형식에 대한 오버로드를 만들려면

지원하려는 각 형식에 대한 특정 오버로드를 만들 수 있습니다. 다음 코드 예제에서는 형식에 Median 대한 메서드의 오버로드를 보여 있습니다 integer .

' Integer overload
<Extension()>
Function Median(ByVal source As IEnumerable(Of Integer)) As Double
    Return Aggregate num In source Select CDbl(num) Into med = Median()
End Function

이제 다음 코드와 같이 형식과 Median 형식 모두 integer 에 대한 오버로드를 호출 double 할 수 있습니다.

Dim numbers1() As Double = {1.9, 2, 8, 4, 5.7, 6, 7.2, 0}

Dim query1 = Aggregate num In numbers1 Into Median()

Console.WriteLine("Double: Median = " & query1)

Dim numbers2() As Integer = {1, 2, 3, 4, 5}

Dim query2 = Aggregate num In numbers2 Into Median()

Console.WriteLine("Integer: Median = " & query2)

' This code produces the following output:
'
' Double: Median = 4.85
' Integer: Median = 3

제네릭 오버로드를 만들려면

제네릭 개체 시퀀스를 허용하는 오버로드를 만들 수도 있습니다. 이 오버로드는 대리자를 매개 변수로 사용하여 제네릭 형식의 개체 시퀀스를 특정 형식으로 변환합니다.

다음 코드는 대리자를 매개 변수로 사용하는 Median 메서드의 Func<T,TResult> 오버로드를 보여줍니다. 이 대리자는 T 형식의 개체를 사용하고 double 형식의 개체를 반환합니다.

' Generic overload.
<Extension()>
Function Median(Of T)(ByVal source As IEnumerable(Of T),
                  ByVal selector As Func(Of T, Double)) As Double
    Return Aggregate num In source Select selector(num) Into med = Median()
End Function

이제 모든 형식의 Median 개체 시퀀스에 대한 메서드를 호출할 수 있습니다. 형식에 고유한 메서드 오버로드가 없는 경우 대리자 매개 변수를 전달해야 합니다. Visual Basic에서는 이 용도로 람다 식을 사용할 수 있습니다. 또한, 메서드 호출 대신 Aggregate 또는 Group By 절을 사용할 경우, 이 절의 범위에 있는 어떤 값이나 식이든 전달할 수 있습니다.

다음 예제 코드는 정수 배열 및 문자열 배열에 대한 메서드를 호출 Median 하는 방법을 보여 줍니다. 문자열의 경우 배열의 문자열 길이에 대한 중앙값이 계산됩니다. 이 예제에서는 각 사례에 Func<T,TResult> 대한 메서드에 대리자 매개 변수를 Median 전달하는 방법을 보여 있습니다.

Dim numbers3() As Integer = {1, 2, 3, 4, 5}

' You can use num as a parameter for the Median method
' so that the compiler will implicitly convert its value to double.
' If there is no implicit conversion, the compiler will
' display an error message.

Dim query3 = Aggregate num In numbers3 Into Median(num)

Console.WriteLine("Integer: Median = " & query3)

Dim numbers4() As String = {"one", "two", "three", "four", "five"}

' With the generic overload, you can also use numeric properties of objects.

Dim query4 = Aggregate str In numbers4 Into Median(str.Length)

Console.WriteLine("String: Median = " & query4)

' This code produces the following output:
'
' Integer: Median = 3
' String: Median = 4

컬렉션을 반환하는 메서드 추가

값의 시퀀스를 반환하는 사용자 지정 쿼리 메서드를 사용하여 IEnumerable<T> 인터페이스를 확장할 수 있습니다. 이 경우 메서드는 형식 IEnumerable<T>의 컬렉션을 반환해야 합니다. 이러한 메서드를 사용하여 값 시퀀스에 필터 또는 데이터 변환을 적용할 수 있습니다.

다음 예제에서는 첫 번째 요소부터 시작하여 컬렉션의 다른 모든 요소를 반환하는 확장 AlternateElements 메서드를 만드는 방법을 보여줍니다.

' Extension method for the IEnumerable(of T) interface.
' The method returns every other element of a sequence.
<Extension()>
Iterator Function AlternateElements(Of T)(
ByVal source As IEnumerable(Of T)
) As IEnumerable(Of T)
    Dim i = 0
    For Each element In source
        If (i Mod 2 = 0) Then
            Yield element
        End If
        i = i + 1
    Next
End Function

다음 코드와 같이 인터페이스에서 다른 메서드를 호출하는 것처럼 열거 가능한 컬렉션에 IEnumerable<T> 대해 이 확장 메서드를 호출할 수 있습니다.

Dim strings() As String = {"a", "b", "c", "d", "e"}

Dim query5 = strings.AlternateElements()

For Each element In query5
    Console.WriteLine(element)
Next

' This code produces the following output:
'
' a
' c
' e

참고하십시오