共用方式為


操作說明:新增 LINQ 查詢的自訂方法 (Visual Basic)

您可以藉由將擴充方法新增至 IEnumerable<T> 介面,來擴充您可以用於 LINQ 查詢的方法集合。 例如,除了標準平均值或最大運算,您可以建立自訂的彙總方法來計算一系列值的單一值。 您也可以建立一個方法,用為自訂篩選器或一系列值的特定資料轉換,並傳回新的序列。 這類方法的範例包括 DistinctSkipReverse

當您延伸 IEnumerable<T> 介面時,可將自訂方法套用至任何可列舉的集合。 如需詳細資訊,請參閱擴充方法

新增彙總方法

彙總方法會計算一組值的單一值。 LINQ 提供數種彙總方法,包括 AverageMinMax。 您可將擴充方法新增至 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 中,您可以使用 AggregateGroup By 子句的方法呼叫或標準查詢語法。 如需詳細資訊,請參閱 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

多載彙總方法以接受各種類型

您可以多載自己的彙總方法,讓它接受各種類型的序列。 標準方法是為每種類型建立多載。 另一種方法是建立採用泛型型別的多載,使用委派將它轉換成特定的類型。 您也可以結合這兩種方法。

為每種類型建立多載

您可以為想要支援的每種類型建立特定的多載。 下列程式碼範例示範適合 integer 類型之 Median 方法的多載。

' 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

您現在可以呼叫 integerdouble 類型的 Median 多載,如下列程式碼所示︰

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 中,您可以針對此目的使用 Lambda 運算式。 另外,如果您使用 AggregateGroup 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

另請參閱