Přidání vlastních metod pro dotazy LINQ (C#)
Sadu metod, které používáte pro dotazy LINQ, rozšíříte přidáním rozšiřujících metod do IEnumerable<T> rozhraní. Kromě standardních průměrných nebo maximálních operací například vytvoříte vlastní agregační metodu pro výpočet jedné hodnoty z posloupnosti hodnot. Vytvoříte také metodu, která funguje jako vlastní filtr nebo konkrétní transformace dat pro sekvenci hodnot a vrací novou sekvenci. Příklady takových metod jsou Distinct, Skipa Reverse.
Když rozhraní rozšíříte IEnumerable<T> , můžete vlastní metody použít na libovolnou výčtové kolekce. Další informace naleznete v tématu Metody rozšíření.
Přidání agregační metody
Agregační metoda vypočítá jednu hodnotu ze sady hodnot. LINQ poskytuje několik agregačních metod, včetně Average, Mina Max. Vlastní agregační metodu můžete vytvořit přidáním rozšiřující metody do IEnumerable<T> rozhraní.
Následující příklad kódu ukazuje, jak vytvořit rozšiřující metodu volanou Median
pro výpočet mediánu pro sekvenci čísel typu double
.
public static class EnumerableExtension
{
public static double Median(this IEnumerable<double>? source)
{
if (source is null || !source.Any())
{
throw new InvalidOperationException("Cannot compute median for a null or empty set.");
}
var sortedList =
source.OrderBy(number => number).ToList();
int itemIndex = sortedList.Count / 2;
if (sortedList.Count % 2 == 0)
{
// Even number of items.
return (sortedList[itemIndex] + sortedList[itemIndex - 1]) / 2;
}
else
{
// Odd number of items.
return sortedList[itemIndex];
}
}
}
Tuto metodu rozšíření voláte pro všechny výčtové kolekce stejným způsobem, jakým voláte jiné agregační metody z IEnumerable<T> rozhraní.
Následující příklad kódu ukazuje, jak použít metodu Median
pro pole typu double
.
double[] numbers = [1.9, 2, 8, 4, 5.7, 6, 7.2, 0];
var query = numbers.Median();
Console.WriteLine($"double: Median = {query}");
// This code produces the following output:
// double: Median = 4.85
Přetížení agregační metody pro příjem různých typů
Agregační metodu můžete přetížit tak, aby přijímala sekvence různých typů. Standardním přístupem je vytvoření přetížení pro každý typ. Dalším přístupem je vytvoření přetížení, které bude mít obecný typ a převést ho na konkrétní typ pomocí delegáta. Můžete také kombinovat oba přístupy.
Vytvoření přetížení pro každý typ
Pro každý typ, který chcete podporovat, můžete vytvořit konkrétní přetížení. Následující příklad kódu ukazuje přetížení Median
metody pro int
typ.
// int overload
public static double Median(this IEnumerable<int> source) =>
(from number in source select (double)number).Median();
Nyní můžete volat Median
přetížení pro oba integer
typy double
, jak je znázorněno v následujícím kódu:
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
// int: Median = 3
Vytvoření obecného přetížení
Můžete také vytvořit přetížení, které přijímá posloupnost obecných objektů. Toto přetížení přebírá delegáta jako parametr a používá ho k převodu posloupnosti objektů obecného typu na určitý typ.
Následující kód ukazuje přetížení Median
metody, která přebírá delegáta Func<T,TResult> jako parametr. Tento delegát přebírá objekt obecného typu T a vrací objekt typu double
.
// generic overload
public static double Median<T>(
this IEnumerable<T> numbers, Func<T, double> selector) =>
(from num in numbers select selector(num)).Median();
Nyní můžete volat metodu Median
pro posloupnost objektů libovolného typu. Pokud typ nemá vlastní přetížení metody, musíte předat parametr delegáta. V jazyce C# můžete pro tento účel použít výraz lambda. V jazyce Visual Basic můžete také pouze v případě, že místo volání metody použijete Aggregate
klauzuli nebo Group By
klauzuli, můžete předat libovolnou hodnotu nebo výraz, který je v oboru této klauzule.
Následující příklad kódu ukazuje, jak volat metodu Median
pro pole celých čísel a pole řetězců. U řetězců se vypočítá medián délky řetězců v poli. Příklad ukazuje, jak předat Func<T,TResult> parametr delegáta Median
metodě pro každý případ.
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:
// int: Median = 3
// string: Median = 4
Přidání metody, která vrací sekvenci
Rozhraní můžete rozšířit IEnumerable<T> vlastní metodou dotazu, která vrací posloupnost hodnot. V tomto případě musí metoda vrátit kolekci typu IEnumerable<T>. Tyto metody lze použít k použití filtrů nebo transformací dat na sekvenci hodnot.
Následující příklad ukazuje, jak vytvořit rozšiřující metodu s názvem AlternateElements
, která vrací všechny ostatní prvky v kolekci počínaje prvním prvkem.
// 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)
{
int index = 0;
foreach (T element in source)
{
if (index % 2 == 0)
{
yield return element;
}
index++;
}
}
Tuto metodu rozšíření můžete volat pro libovolnou výčet kolekcí stejně, jako byste volali jiné metody z IEnumerable<T> rozhraní, jak je znázorněno v následujícím kódu:
string[] strings = ["a", "b", "c", "d", "e"];
var query5 = strings.AlternateElements();
foreach (var element in query5)
{
Console.WriteLine(element);
}
// This code produces the following output:
// a
// c
// e
Viz také
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro