Partilhar via


Como: Adicionar métodos personalizados para consultas LINQ (Visual Basic)

Você estende o conjunto de métodos que você usa para consultas LINQ adicionando métodos de extensão à IEnumerable<T> interface. Por exemplo, além das operações médias ou máximas padrão, você cria um método de agregação personalizado para calcular um único valor a partir de uma sequência de valores. Você também cria um método que funciona como um filtro personalizado ou uma transformação de dados específica para uma sequência de valores e retorna uma nova sequência. Exemplos de tais métodos são Distinct, Skip, e Reverse.

Ao estender a IEnumerable<T> interface, você pode aplicar seus métodos personalizados a qualquer coleção enumerável. Para obter mais informações, consulte Métodos de extensão.

Adicionando um método agregado

Um método agregado calcula um único valor a partir de um conjunto de valores. O LINQ fornece vários métodos agregados, incluindo Average, Mine Max. Você pode criar seu próprio método de agregação adicionando um método de extensão à IEnumerable<T> interface.

O exemplo de código a seguir mostra como criar um método de extensão chamado Median para calcular uma mediana para uma sequência de números do tipo 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

Você chama esse método de extensão para qualquer coleção enumerável da mesma forma que chama outros métodos agregados da IEnumerable<T> interface.

Nota

No Visual Basic, você pode usar uma chamada de método ou sintaxe de consulta padrão para a Aggregate cláusula ou Group By . Para obter mais informações, consulte Cláusula agregada e Agrupar por cláusula.

O exemplo de código a seguir mostra como usar o Median método para uma matriz do tipo 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

Sobrecarregando um método agregado para aceitar vários tipos

Você pode sobrecarregar seu método agregado para que ele aceite sequências de vários tipos. A abordagem padrão é criar uma sobrecarga para cada tipo. Outra abordagem é criar uma sobrecarga que tomará um tipo genérico e o converterá em um tipo específico usando um delegado. Você também pode combinar ambas as abordagens.

Para criar uma sobrecarga para cada tipo

Você pode criar uma sobrecarga específica para cada tipo que deseja suportar. O exemplo de código a seguir mostra uma sobrecarga do Median método para o integer tipo.

' 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

Agora você pode chamar as Median sobrecargas para ambos e doubleinteger tipos, conforme mostrado no código a seguir:

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

Para criar uma sobrecarga genérica

Você também pode criar uma sobrecarga que aceita uma sequência de objetos genéricos. Essa sobrecarga usa um delegado como parâmetro e o usa para converter uma sequência de objetos de um tipo genérico em um tipo específico.

O código a seguir mostra uma sobrecarga do método que toma o MedianFunc<T,TResult> delegado como um parâmetro. Este delegado pega um objeto de tipo T genérico e retorna um objeto de tipo 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

Agora você pode chamar o Median método para uma sequência de objetos de qualquer tipo. Se o tipo não tiver sua própria sobrecarga de método, você terá que passar um parâmetro delegado. No Visual Basic, você pode usar uma expressão lambda para essa finalidade. Além disso, se você usar a Aggregate cláusula ou Group By em vez da chamada de método, poderá passar qualquer valor ou expressão que esteja no escopo desta cláusula.

O código de exemplo a seguir mostra como chamar o Median método para uma matriz de inteiros e uma matriz de cadeias de caracteres. Para strings, a mediana para os comprimentos de strings na matriz é calculada. O exemplo mostra como passar o Func<T,TResult> parâmetro delegate para o Median método para cada caso.

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

Adicionando um método que retorna uma coleção

Você pode estender a IEnumerable<T> interface com um método de consulta personalizado que retorna uma sequência de valores. Nesse caso, o método deve retornar uma coleção do tipo IEnumerable<T>. Tais métodos podem ser usados para aplicar filtros ou transformações de dados a uma sequência de valores.

O exemplo a seguir mostra como criar um método de extensão chamado AlternateElements que retorna todos os outros elementos em uma coleção, começando a partir do primeiro elemento.

' 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

Você pode chamar esse método de extensão para qualquer coleção enumerável da mesma forma que chamaria outros métodos da IEnumerable<T> interface, conforme mostrado no código a seguir:

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

Consulte também