Freigeben über


Vorgehensweise: Hinzufügen von benutzerdefinierten Methoden für LINQ-Abfragen (Visual Basic)

Sie erweitern den Satz von Methoden, die Sie für LINQ-Abfragen verwenden, indem Sie der IEnumerable<T> Schnittstelle Erweiterungsmethoden hinzufügen. Zusätzlich zu den standarddurchschnittlichen oder maximalen Vorgängen erstellen Sie beispielsweise eine benutzerdefinierte Aggregatmethode, um einen einzelnen Wert aus einer Folge von Werten zu berechnen. Sie erstellen auch eine Methode, die als benutzerdefinierter Filter oder eine bestimmte Datentransformation für eine Abfolge von Werten funktioniert und eine neue Sequenz zurückgibt. Beispiele für solche Methoden sind Distinct, Skipund Reverse.

Wenn Sie die IEnumerable<T> Schnittstelle erweitern, können Sie Ihre benutzerdefinierten Methoden auf jede aufzählbare Auflistung anwenden. Weitere Informationen finden Sie unter Erweiterungsmethoden.

Hinzufügen einer Aggregatmethode

Eine Aggregatmethode berechnet einen einzelnen Wert aus einer Gruppe von Werten. LINQ stellt verschiedene Aggregatmethoden bereit, einschließlich Average, Minund Max. Sie können eine eigene Aggregatmethode erstellen, indem Sie der IEnumerable<T> Schnittstelle eine Erweiterungsmethode hinzufügen.

Das folgende Codebeispiel zeigt, wie eine Erweiterungsmethode namens Median erstellt wird, um einen Median für eine Sequenz von Zahlen vom Typ double zu berechnen.

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

Sie rufen diese Erweiterungsmethode für jede aufzählbare Auflistung auf die gleiche Weise auf, wie Sie andere Aggregatmethoden von der IEnumerable<T> Schnittstelle aufrufen.

Hinweis

In Visual Basic können Sie entweder einen Methodenaufruf oder die Standardabfragesyntax für die Aggregate- oder Group By-Klausel verwenden. Weitere Informationen finden Sie unter Aggregate Clause und Group By Clause.

Das folgende Codebeispiel zeigt, wie die Median Methode für ein Array vom Typ doubleverwendet wird.

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

Überladen einer Aggregatmethode zum Akzeptieren verschiedener Typen

Sie können die Aggregatmethode überladen, sodass sie Sequenzen verschiedener Typen akzeptiert. Der Standardansatz besteht darin, für jeden Typ eine Überladung zu erstellen. Ein anderer Ansatz ist das Erstellen einer Überladung, die einen generischen Typ annimmt und diesen mit einem Delegaten in einen bestimmten Typ konvertiert. Sie können auch beide Ansätze kombinieren.

So erstellen Sie eine Überladung für jeden Typ

Sie können für jeden typ, den Sie unterstützen möchten, eine bestimmte Überladung erstellen. Das folgende Codebeispiel zeigt eine Überladung der Median Methode für den integer Typ.

' 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

Sie können jetzt die Median-Überladungen für beide(n) integer und double-Typen aufrufen, wie im folgenden Code gezeigt:

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

So erstellen Sie eine generische Überladung

Sie können auch eine Überladung erstellen, die eine Abfolge generischer Objekte akzeptiert. Diese Überladung verwendet einen Delegaten als Parameter und verwendet ihn, um eine Abfolge von Objekten eines generischen Typs in einen bestimmten Typ zu konvertieren.

Der folgende Code zeigt eine Überladung der Median Methode, die den Func<T,TResult> Delegaten als Parameter verwendet. Dieser Delegat akzeptiert ein Objekt vom generischen Typ T und gibt ein Objekt vom Typ zurück 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

Sie können die Median Methode jetzt für eine Abfolge von Objekten eines beliebigen Typs aufrufen. Wenn der Typ nicht über eine eigene Methodenüberladung verfügt, müssen sie einen Delegatenparameter übergeben. In Visual Basic können Sie hierfür einen Lambda-Ausdruck verwenden. Wenn Sie die Aggregate Oder-Klausel Group By anstelle des Methodenaufrufs verwenden, können Sie auch einen beliebigen Wert oder Ausdruck übergeben, der sich im Bereich dieser Klausel befindet.

Im folgenden Beispielcode wird gezeigt, wie die Median Methode für ein Array ganzzahliger Zahlen und ein Array von Zeichenfolgen aufgerufen wird. Bei Zeichenfolgen wird der Median für die Längen von Zeichenfolgen im Array berechnet. Das Beispiel zeigt, wie der Func<T,TResult> Delegatparameter für jeden Fall an die Median Methode übergeben wird.

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

Hinzufügen einer Methode, die eine Auflistung zurückgibt

Sie können die IEnumerable<T> Schnittstelle mit einer benutzerdefinierten Abfragemethode erweitern, die eine Abfolge von Werten zurückgibt. In diesem Fall muss die Methode eine Sammlung vom Typ IEnumerable<T>zurückgeben. Solche Methoden können verwendet werden, um Filter oder Datentransformationen auf eine Abfolge von Werten anzuwenden.

Das folgende Beispiel zeigt, wie Sie eine Erweiterungsmethode AlternateElements erstellen, die jedes andere Element in einer Auflistung zurückgibt, beginnend mit dem ersten Element.

' 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

Sie können diese Erweiterungsmethode für jede aufzählbare Auflistung genauso aufrufen, wie sie andere Methoden aus der IEnumerable<T> Schnittstelle aufrufen würden, wie im folgenden Code gezeigt:

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

Siehe auch