Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Вы расширяете набор методов, используемых для запросов LINQ, добавив методы расширения в IEnumerable<T> интерфейс. Например, помимо стандартных средних или максимальных операций, вы создадите пользовательский агрегатный метод для вычисления одного значения из последовательности значений. Вы также создаете метод, который работает в качестве пользовательского фильтра или определенного преобразования данных для последовательности значений и возвращает новую последовательность. Примерами таких методов являются 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 предложения. Дополнительные сведения см. в агрегатном предложении и предложении 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 для этой цели можно использовать лямбда-выражение. Кроме того, если вместо вызова метода используется предложение 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