Compartir a través de


Cómo: Agregar métodos personalizados para consultas LINQ (Visual Basic)

Puede ampliar el conjunto de métodos que se usan para las consultas LINQ agregando métodos de extensión a la IEnumerable<T> interfaz . Por ejemplo, además de las operaciones medias o máximas estándar, se crea un método de agregado personalizado para calcular un valor único a partir de una secuencia de valores. También se crea un método que funciona como un filtro personalizado o una transformación de datos específica para una secuencia de valores y devuelve una nueva secuencia. Algunos ejemplos de estos métodos son Distinct, Skipy Reverse.

Al extender la IEnumerable<T> interfaz, puede aplicar los métodos personalizados a cualquier colección enumerable. Para obtener más información, vea Métodos de extensión.

Adición de un método de agregado

Un método de agregado calcula un valor único a partir de un conjunto de valores. LINQ proporciona varios métodos agregados, incluidos Average, Miny Max. Puede crear su propio método de agregado agregando un método de extensión a la IEnumerable<T> interfaz.

En el ejemplo de código siguiente se muestra cómo crear un método de extensión llamado Median para calcular una mediana para una secuencia de números de 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

Utilizas este método de extensión para cualquier colección enumerable de la misma manera que llamar a otros métodos agregados de la interfaz IEnumerable<T>.

Nota:

En Visual Basic, puede usar una llamada de método o una sintaxis de consulta estándar para las cláusulas Aggregate o Group By. Para más información, consulte Cláusula Aggregate y Cláusula Group By.

En el ejemplo de código siguiente se muestra cómo usar el Median método para una matriz de 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

Sobrecargar un método de agregación para que acepte varios tipos

Puede sobrecargar el método de agregado para que acepte secuencias de varios tipos. El enfoque estándar consiste en crear una sobrecarga para cada tipo. Otro enfoque consiste en crear una sobrecarga que tome un tipo genérico y lo convierta a un tipo específico mediante un delegado. También puede combinar ambos enfoques.

Para crear una sobrecarga para cada tipo

Puede crear una sobrecarga específica para cada tipo que desee admitir. En el ejemplo de código siguiente se muestra una sobrecarga del Median método para el 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

Ahora puede llamar a las sobrecargas Median para los tipos integer y double, como se muestra en el código siguiente:

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 crear una sobrecarga genérica

También puede crear una sobrecarga que acepte una secuencia de objetos genéricos. Esta sobrecarga toma un delegado como parámetro y lo usa para convertir una secuencia de objetos de un tipo genérico a un tipo específico.

El código siguiente muestra una sobrecarga del Median método que toma el Func<T,TResult> delegado como parámetro. Este delegado toma un objeto de tipo T genérico y devuelve un 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

Ahora puede llamar al Median método para una secuencia de objetos de cualquier tipo. Si el tipo no tiene su propia sobrecarga de métodos, deberá pasar un parámetro de delegado. En Visual Basic, puede usar una expresión lambda para este propósito. Además, si usa la Aggregate cláusula o Group By en lugar de la llamada al método, puede pasar cualquier valor o expresión que esté en el ámbito de esta cláusula.

En el código de ejemplo siguiente se muestra cómo llamar al Median método para una matriz de enteros y una matriz de cadenas. En el caso de las cadenas, se calcula la mediana de las longitudes de las cadenas de la matriz. En el ejemplo se muestra cómo pasar el Func<T,TResult> parámetro delegado al 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

Adición de un método que devuelve una colección

Puede ampliar la IEnumerable<T> interfaz con un método de consulta personalizado que devuelva una secuencia de valores. En este caso, el método debe devolver una colección de tipo IEnumerable<T>. Estos métodos se pueden usar para aplicar filtros o transformaciones de datos a una secuencia de valores.

En el ejemplo siguiente se muestra cómo crear un método de extensión denominado AlternateElements que devuelve todos los demás elementos de una colección, empezando por el primer 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

Puede llamar a este método de extensión para cualquier colección enumerable igual que llamaría a otros métodos desde la IEnumerable<T> interfaz, como se muestra en el código siguiente:

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 también