共用方式為


如何:新增 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 中,您可以使用 Aggregate 子句的方法呼叫或 Group 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

重載聚合方法以接受各種資料類型

您可以多載匯總方法,使其接受各種類型的序列。 標準方法是為每個型別創建多載。 另一種方法是建立採用泛型型別的多載,並使用委派將其轉換成特定類型。 您也可以合併這兩種方法。

若要為每個類型建立多載

您可以為每個想要支援的類型建立特定的多載。 下列程式碼範例顯示了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 的多載,適用於 integerdouble 類型,如下列程式代碼所示:

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

另請參閱