Guide pratique : ajouter des méthodes personnalisées pour les requêtes LINQ (Visual Basic)

Vous étendez l’ensemble de méthodes que vous utilisez pour les requêtes LINQ en ajoutant des méthodes d’extension à l’interface IEnumerable<T>. Par exemple, en plus des opérations moyennes ou maximales standard, vous créez une méthode d’agrégation personnalisée pour calculer une valeur unique à partir d’une séquence de valeurs. Vous pouvez également créer une méthode qui fonctionne comme un filtre personnalisé ou une transformation de données pour une séquence de valeurs, et qui retourne une nouvelle séquence. Distinct, Skip et Reverse en sont quelques exemples.

Quand vous étendez l’interface IEnumerable<T>, vous pouvez appliquer vos méthodes personnalisées à n’importe quelle collection énumérable. Pour plus d’informations, consultez Méthodes d’extension.

Utilisation d’une méthode d’agrégation

Une méthode d’agrégation calcule une valeur à partir d’un ensemble de valeurs. LINQ fournit plusieurs méthodes d’agrégation, notamment Average, Min et Max. Vous pouvez créer votre propre méthode d’agrégation en ajoutant une méthode d’extension à l’interface IEnumerable<T>.

L’exemple de code suivant montre comment créer une méthode d’extension appelée Median pour calculer une valeur médiane pour une séquence de nombres de type 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

Vous appelez cette méthode d’extension pour toute collection énumérable de la même façon que vous appelez d’autres méthodes d’agrégation depuis l’interface IEnumerable<T>.

Notes

Dans Visual Basic, vous pouvez utiliser un appel de méthode ou une syntaxe de requête standard pour la clause Aggregate ou Group By. Pour plus d’informations, consultez Clause Aggregate et Clause Group By.

L’exemple de code suivant montre comment utiliser la méthode Median pour un tableau de type 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

Surcharge d’une méthode d’agrégation pour accepter différents types

Vous pouvez surcharger votre méthode d’agrégation pour qu’elle accepte des séquences de différents types. L’approche standard consiste à créer une surcharge pour chaque type. Une autre approche consiste à créer une surcharge qui accepte un type générique et le convertit en un autre type à l’aide d’un délégué. Vous pouvez également combiner ces deux approches.

Pour créer une surcharge pour chaque type

Vous pouvez créer une surcharge pour chacun des types que vous voulez prendre en charge. L’exemple de code suivant montre une surcharge de la méthode Median pour le type 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

Vous pouvez maintenant appeler les surcharges Median pour les types integer et double, comme indiqué dans le code suivant :

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

Pour créer une surcharge générique

Vous pouvez également créer une surcharge qui accepte une séquence d’objets génériques. Cette surcharge prend un délégué comme paramètre et l’utilise pour convertir une séquence d’objets de type générique en un autre type d’objets.

Le code suivant montre une surcharge de la méthode Median qui prend le délégué Func<T,TResult> comme paramètre. Ce délégué prend un objet de type générique T et retourne un objet de type 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

Vous pouvez maintenant appeler la méthode Median pour une séquence d’objets de tout type. Si le type n’a pas sa propre surcharge de méthode, vous devez passer un paramètre délégué. En Visual Basic, vous pouvez utiliser une expression lambda à cet effet. En outre, si vous utilisez la clause Aggregate ou Group By au lieu de l’appel de méthode, vous pouvez passer n’importe quelle valeur ou expression qui se trouve dans la portée de cette clause.

L’exemple de code suivant montre comment appeler la méthode Median pour un tableau d’entiers et un tableau de chaînes. Pour les chaînes, c’est la valeur médiane des longueurs de chaînes du tableau qui est calculée. L’exemple montre comment passer le paramètre de délégué Func<T,TResult> à la méthode Median pour chaque cas.

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

Ajout d’une méthode qui retourne une collection

Vous pouvez étendre l’interface IEnumerable<T> avec une méthode de requête personnalisée qui retourne une séquence de valeurs. Dans ce cas, la méthode doit retourner une collection de type IEnumerable<T>. Ces méthodes peuvent être utilisées pour appliquer des filtres ou des transformations de données à une séquence de valeurs.

L’exemple suivant montre comment créer une méthode d’extension nommée AlternateElements qui retourne un élément sur deux d’une collection, en commençant par le premier élément.

' 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

Vous pouvez appeler cette méthode d’extension pour n’importe quelle collection énumérable, de la même façon que vous appelez d’autres méthodes depuis l’interface IEnumerable<T>, comme le montre le code suivant :

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

Voir aussi