Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Minden LINQ-alapú metódus két hasonló minta egyikét követi. Számba vehetnek egy sorozatot. Egy másik sorozatot vagy egyetlen értéket adnak vissza. Az alakzat konzisztenciája lehetővé teszi a LINQ kiterjesztését egy hasonló alakzatot tartalmazó metódusok írásával. Valójában a .NET-kódtárak számos .NET-kiadásban új módszereket kaptak a LINQ első bevezetése óta. Ebben a cikkben példákat láthat a LINQ kiterjesztésére az azonos mintát követő saját metódusok megírásával.
Egyéni metódusok hozzáadása LINQ-lekérdezésekhez
Bővítse a LINQ-lekérdezésekhez használt metódusokat úgy, hogy bővítő metódusokat ad hozzá a IEnumerable<T> felülethez. A standard átlag vagy a maximális műveletek mellett például létrehozhat egy egyéni összesítési módszert, amellyel egyetlen értéket számíthat ki egy értéksorozatból. Olyan metódust is létrehozhat, amely egyéni szűrőként vagy adott adatátalakításként működik egy értéksorozathoz, és egy új sorozatot ad vissza. Ilyen módszerek például a Distinctkövetkezők: , Skipés Reverse.
Ha kibővíti a IEnumerable<T> felületet, az egyéni metódusokat bármilyen számba vehet gyűjteményre alkalmazhatja. További információ: Bővítménytagok.
Az összesítő metódus egyetlen értéket számít ki egy értékkészletből. A LINQ számos aggregátummetszetet biztosít, köztük Averagea . MinMax Hozzon létre egy saját összesítő metódust úgy, hogy hozzáad egy bővítménymetódust a IEnumerable<T> felülethez.
A C# 14-től kezdődően deklarálhat egy bővítményblokkot , amely több bővítménytagot tartalmaz. Deklarál egy bővítményblokkot a kulcsszóval extension , majd zárójelben a fogadó paraméterrel. Az alábbi példakód bemutatja, hogyan hozhat létre bővítményblokkban meghívott Median bővítménymetódusokat. A metódus kiszámítja a mediánt egy számsorozat doubletípusához .
extension(IEnumerable<double>? source)
{
public double Median()
{
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];
}
}
}
A módosító statikus this metódushoz is hozzáadható a bővítménymetódus deklarálásához. Az alábbi kód az egyenértékű Median bővítménymetódust mutatja be:
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];
}
}
}
Bármely számozható gyűjtemény bármelyik bővítménymetódusát ugyanúgy hívhatja meg, mint a felületről származó IEnumerable<T> összesítő metódusokat.
Az alábbi példakód bemutatja, hogyan használhatja a Median metódust egy típustömbhöz 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
Túlterhelje az összesített metódust , hogy különböző típusú sorozatokat fogadjon el. A szokásos módszer az, hogy minden típushoz túlterhelést kell létrehozni. Egy másik módszer egy olyan túlterhelés létrehozása, amely egy általános típust vesz igénybe, és egy meghatalmazott használatával átalakítja azt egy adott típusra. Mindkét megközelítést kombinálhatja is.
Hozzon létre egy adott túlterhelést minden támogatni kívánt típushoz. Az alábbi példakód a Median metódus túlterhelését mutatja be a int típushoz.
// int overload
public static double Median(this IEnumerable<int> source) =>
(from number in source select (double)number).Median();
Most már meghívhatja a Median túlterheléseket mindkét integer és double típus esetében, ahogyan az az alábbi kódban is látható:
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
Olyan túlterhelést is létrehozhat, amely elfogadja az objektumok általános sorozatát . Ez a túlterhelés egy delegáltat vesz fel paraméterként, és arra használja, hogy egy általános típusú objektumsorozatot egy adott típussá alakítson.
Az alábbi kód a metódus túlterhelését Median mutatja, amely a Func<T,TResult> delegáltat paraméterként veszi fel. Ez a meghatalmazott egy általános T típusú objektumot vesz fel, és egy típusobjektumot doublead vissza.
// generic overload
public static double Median<T>(
this IEnumerable<T> numbers, Func<T, double> selector) =>
(from num in numbers select selector(num)).Median();
Mostantól bármilyen típusú objektumsorozathoz meghívhatja a Median metódust. Ha a típus nem rendelkezik saját metódusterheléssel, adjon át egy delegált paramétert. A C#-ban erre a célra használhat lambda kifejezést. Emellett, csak a Visual Basicben, ha a metódushívás helyett a Aggregate vagy a Group By záradékot használja, a záradék hatókörében lévő bármely értéket vagy kifejezést átadhat.
Az alábbi példakód bemutatja, hogyan hívhatja meg a Median metódust egész számok tömbjének és egy sztringtömbnek. Sztringek esetén a tömbben lévő sztringek hosszának mediánját számítja ki a rendszer. A példa bemutatja, hogyan adhatja át a Func<T,TResult> delegált paramétert az Median egyes esetek metódusának.
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
Bővítse a IEnumerable<T> felületet egy egyéni lekérdezési módszerrel, amely értéksorozatot ad vissza. Ebben az esetben a metódusnak egy típusgyűjteményt IEnumerable<T>kell visszaadnia. Ilyen módszerekkel szűrőket vagy adatátalakításokat alkalmazhat értékek sorozatára.
Az alábbi példa bemutatja, hogyan hozhat létre egy olyan bővítménymetódust, AlternateElements amely egy gyűjtemény minden más elemét visszaadja az első elemtől kezdve.
// 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++;
}
}
Hívja meg ezt a bővítménymetódust minden számbavehető gyűjteményhez ugyanúgy, ahogyan más metódusokat is meghívna a IEnumerable<T> felületről, ahogyan az alábbi kódban látható:
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
A cikkben bemutatott példák mindegyike más fogadóval rendelkezik. Ez azt jelenti, hogy minden metódust egy másik bővítményblokkban kell deklarálnia, amely megadja az egyedi fogadót. Az alábbi példakód egyetlen statikus osztályt mutat be három különböző bővítményblokkgal, amelyek mindegyike a cikkben meghatározott módszerek egyikét tartalmazza:
public static class EnumerableExtension
{
extension(IEnumerable<double>? source)
{
public double Median()
{
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];
}
}
}
extension(IEnumerable<int> source)
{
public double Median() =>
(from number in source select (double)number).Median();
}
extension<T>(IEnumerable<T> source)
{
public double Median(Func<T, double> selector) =>
(from num in source select selector(num)).Median();
public IEnumerable<T> AlternateElements()
{
int index = 0;
foreach (T element in source)
{
if (index % 2 == 0)
{
yield return element;
}
index++;
}
}
}
}
A végső bővítményblokk általános bővítményblokkot deklarál. A fogadó típusparamétere önmagában extension deklarálva van.
Az előző példa minden bővítményblokkban egy bővítménytagot deklarál. A legtöbb esetben több bővítménytagot hoz létre ugyanahhoz a fogadóhoz. Ezekben az esetekben deklarálja a tagok bővítményeit egyetlen bővítményblokkban.