Postupy: Přidávání vlastních metod do dotazů LINQ
Sada metod, které lze použít pro LINQ dotazy přidáním rozšíření metody lze rozšířit IEnumerable rozhraní.Vedle standardní průměr nebo maximální operací, například můžete vytvořit vlastní agregační metoda vypočítat jedinou hodnotu z řady hodnot.Můžete také vytvořit metodu, která funguje jako vlastní filtr nebo transformaci dat specifických pro posloupnost hodnot a vrátí nové pořadí.Příklady takových metod Distinct``1, Skip``1, a Reverse``1.
Jestliže rozšiřujete IEnumerable rozhraní, vlastní metody můžete aplikovat na všechny agregující kolekce.Další informace naleznete v tématech Metody rozšíření (Průvodce programováním v C#) a Metody rozšíření (Visual Basic).
Přidání agregační metoda
Agregační metoda vypočítá jednu hodnotu v množině hodnot.LINQ poskytuje několik metod agregační, včetně Average``1, Min``1, a Max``1.Můžete vytvořit vlastní metodu agregační přidáním metody rozšíření IEnumerable rozhraní.
Následující příklad kódu ukazuje, jak vytvořit metodu rozšíření nazývá Median vypočítat střední pro posloupnost čísel typu 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 source.Count = 0 Then
Throw New InvalidOperationException("Cannot compute median for an empty set.")
End If
Dim sortedSource = From number In source
Order By number
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
public static class LINQExtension
{
public static double Median(this IEnumerable<double> source)
{
if (source.Count() == 0)
{
throw new InvalidOperationException("Cannot compute median for an empty set.");
}
var sortedList = from number in source
orderby number
select number;
int itemIndex = (int)sortedList.Count() / 2;
if (sortedList.Count() % 2 == 0)
{
// Even number of items.
return (sortedList.ElementAt(itemIndex) + sortedList.ElementAt(itemIndex - 1)) / 2;
}
else
{
// Odd number of items.
return sortedList.ElementAt(itemIndex);
}
}
}
Volání této metody rozšíření pro všechny kolekce agregující stejným způsobem volat jiné agregační metody z IEnumerable rozhraní.
[!POZNÁMKA]
V jazyce Visual Basic můžete použít buď volání metody nebo dotazu standardní syntaxe Aggregate nebo Group By klauzule.Další informace naleznete v tématu Aggregate – klauzule (Visual Basic) a Group By – klauzule (Visual Basic).
Následující příklad kódu ukazuje, jak použít Median metoda pro pole typu 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)
...
' This code produces the following output:
'
' Double: Median = 4.85
double[] numbers1 = { 1.9, 2, 8, 4, 5.7, 6, 7.2, 0 };
var query1 = numbers1.Median();
Console.WriteLine("double: Median = " + query1);
...
/*
This code produces the following output:
Double: Median = 4.85
*/
Metodu agregační přijímat různé typy přetížení
Vaše agregační metoda může přetížit tak, že přijímá sekvence různých typů.Standardní možností je vytvořit při přetížení pro každý typ.Další možností je vytvořit při přetížení, který bude trvat obecný typ a převést na určitý typ pomocí delegáta.Můžete také kombinovat oba přístupy.
Vytvoření nadměrného pro každý typ
Můžete vytvořit konkrétní přetížení pro každý typ, který chcete podporovat.Následující příklad kódu ukazuje nadměrného počtu Median metodu integer typu.
' 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
//int overload
public static double Median(this IEnumerable<int> source)
{
return (from num in source select (double)num).Median();
}
Nyní můžete volat Median přetížení pro oba integer a double typy, jak je znázorněno v následujícím kódu:
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
double[] numbers1 = { 1.9, 2, 8, 4, 5.7, 6, 7.2, 0 };
var query1 = numbers1.Median();
Console.WriteLine("double: Median = " + query1);
...
int[] numbers2 = { 1, 2, 3, 4, 5 };
var query2 = numbers2.Median();
Console.WriteLine("int: Median = " + query2);
...
/*
This code produces the following output:
Double: Median = 4.85
Integer: Median = 3
*/
Vytvořit obecný přetížení
Můžete také vytvořit při přetížení, který přijímá posloupnost obecné objekty.Toto přetížení bere jako parametr delegáta a používá pořadí objektů obecný typ převést na určitý typ.
Následující kód ukazuje nadměrného počtu Median metoda, která trvá Func jako parametr delegáta.Tento delegát přijímá objekt obecného typu t a vrací objekt typu 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
// Generic overload.
public static double Median<T>(this IEnumerable<T> numbers,
Func<T, double> selector)
{
return (from num in numbers select selector(num)).Median();
}
Nyní můžete volat Median metoda pro posloupnost objektů libovolného typu.Pokud typ nemá vlastní metodu přetížení, musíte předat parametr delegáta.V jazyce Visual Basic a C# můžete pro tento účel lambda výraz.Také v jazyce Visual Basic, pouze pokud použijete Aggregate nebo Group By klauzule namísto volání metody můžete předat libovolná hodnota nebo výraz, který je v oboru tuto klauzuli.
Následující příklad kódu ukazuje, jak volat Median metoda pro pole celých čísel a pole řetězců.Řetězce se vypočte střední pro délku řetězce v poli.Příklad ukazuje, jak předat Func parametr delegovat Median metoda pro každý případ.
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
int[] numbers3 = { 1, 2, 3, 4, 5 };
/*
You can use the num=>num lambda expression 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.
*/
var query3 = numbers3.Median(num => num);
Console.WriteLine("int: Median = " + query3);
string[] numbers4 = { "one", "two", "three", "four", "five" };
// With the generic overload, you can also use numeric properties of objects.
var query4 = numbers4.Median(str => str.Length);
Console.WriteLine("String: Median = " + query4);
/*
This code produces the following output:
Integer: Median = 3
String: Median = 4
*/
Přidání metodu, která vrátí kolekci
Lze rozšířit IEnumerable rozhraní metodou vlastní dotaz, který vrací pořadí hodnot.V tomto případě metoda musí vrátit typ kolekce IEnumerable.Tyto metody lze použít filtry nebo data transformace na posloupnost hodnot.
Následující příklad ukazuje, jak vytvořit metodu rozšíření s názvem AlternateElements v kolekci, počínaje prvním prvkem, který vrací každý jiný prvek.
' Extension method for the IEnumerable(of T) interface.
' The method returns every other element of a sequence.
<Extension()>
Function AlternateElements(Of T)(
ByVal source As IEnumerable(Of T)
) As IEnumerable(Of T)
Dim list As New List(Of T)
Dim i = 0
For Each element In source
If (i Mod 2 = 0) Then
list.Add(element)
End If
i = i + 1
Next
Return list
End Function
// Extension method for the IEnumerable<T> interface.
// The method returns every other element of a sequence.
public static IEnumerable<T> AlternateElements<T>(this IEnumerable<T> source)
{
List<T> list = new List<T>();
int i = 0;
foreach (var element in source)
{
if (i % 2 == 0)
{
list.Add(element);
}
i++;
}
return list;
}
Tuto metodu rozšíření lze volat pro všechny kolekce agregující stejně, jako by volání jiných metod z IEnumerable rozhraní, viz následující kód:
Dim strings() As String = {"a", "b", "c", "d", "e"}
Dim query = strings.AlternateElements()
For Each element In query
Console.WriteLine(element)
Next
' This code produces the following output:
'
' a
' c
' e
string[] strings = { "a", "b", "c", "d", "e" };
var query = strings.AlternateElements();
foreach (var element in query)
{
Console.WriteLine(element);
}
/*
This code produces the following output:
a
c
e
*/
Viz také
Referenční dokumentace
Metody rozšíření (Průvodce programováním v C#)