您可以藉由將擴充方法新增至 IEnumerable<T> 介面,來擴充用於LINQ查詢的方法集合。 例如,除了標準平均值或最大作業之外,您還可以建立自定義匯總方法,從值序列計算單一值。 您也會建立一個方法,作為一個用於數值序列的自定義篩選器或特定的數據轉換方法,並傳回新的序列。 這類方法的範例包括 Distinct、 Skip和 Reverse。
當您擴充 IEnumerable<T> 介面時,您可以將自定義方法套用至任何可列舉的集合。 如需詳細資訊,請參閱擴充方法。
新增匯總方法
匯總方法會從一組值計算單一值。 LINQ 提供數個匯總方法,包括 Average、 Min和 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 子句的標準查詢語法。 如需詳細資訊,請參閱 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 中,您可以針對此目的使用 Lambda 運算式。 此外,如果您使用 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