Vorgehensweise: Hinzufügen von benutzerdefinierten Methoden zu LINQ-Abfragen (C#)How to: Add Custom Methods for LINQ Queries (C#)

Sie können die Methoden erweitern, die Sie für LINQ-Abfragen durch Hinzufügen von Erweiterungsmethoden zur IEnumerable<T>-Schnittstelle verwenden können.You can extend the set of methods that you can use for LINQ queries by adding extension methods to the IEnumerable<T> interface. Zusätzlich zu den durchschnittlichen oder maximalen Standardvorgängen, können Sie eine benutzerdefinierte Aggregatmethode erstellen, um einen einzelnen Wert aus einer Sequenz von Werten zu berechnen.For example, in addition to the standard average or maximum operations, you can create a custom aggregate method to compute a single value from a sequence of values. Sie können auch eine Methode erstellen, die als benutzerdefinierter Filter oder spezifische Datentransformation für eine Sequenz von Werten agiert und eine neue Sequenz zurückgibt.You can also create a method that works as a custom filter or a specific data transform for a sequence of values and returns a new sequence. Beispiele für solche Methoden sind Distinct, Skip und Reverse.Examples of such methods are Distinct, Skip, and Reverse.

Beim Erweitern der IEnumerable<T>-Schnittstelle können Sie die benutzerdefinierten Methoden auf jede aufzählbare Auflistung anwenden.When you extend the IEnumerable<T> interface, you can apply your custom methods to any enumerable collection. Weitere Informationen finden Sie unter Erweiterungsmethoden.For more information, see Extension Methods.

Hinzufügen einer AggregatmethodeAdding an Aggregate Method

Eine aggregierte Methode berechnet einen einzelnen Wert aus einer Gruppe von Werten.An aggregate method computes a single value from a set of values. LINQ stellt mehrere Aggregatmethoden bereit, einschließlich Average, Min und Max.LINQ provides several aggregate methods, including Average, Min, and Max. Sie können Ihre eigene Aggregatmethode erstellen, indem Sie der IEnumerable<T>-Schnittstelle eine Erweiterungsmethode hinzufügen.You can create your own aggregate method by adding an extension method to the IEnumerable<T> interface.

Im folgenden Codebeispiel wird veranschaulicht, wie eine Erweiterungsmethode namens Median erstellt wird, um einen Median für eine Zahlensequenz des Typs double zu berechnen.The following code example shows how to create an extension method called Median to compute a median for a sequence of numbers of type double.

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);  
        }  
    }  
}  

Sie können diese Erweiterungsmethode für jede aufzählbare Auflistung genau so aufrufen, wie Sie andere Aggregatmethoden aus der IEnumerable<T>-Schnittstelle aufrufen.You call this extension method for any enumerable collection in the same way you call other aggregate methods from the IEnumerable<T> interface.

Im folgenden Codebeispiel wird die Verwendung der Median-Methode für ein Array des Typs double veranschaulicht.The following code example shows how to use the Median method for an array of type double.

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  
*/  

Überladen einer Aggregatmethode zum Akzeptieren verschiedener TypenOverloading an Aggregate Method to Accept Various Types

Sie können die Aggregatmethode überladen, sodass diese Sequenzen verschiedener Typen akzeptiert.You can overload your aggregate method so that it accepts sequences of various types. Die Standardmethode ist die Erstellung einer Überladung für jeden Typ.The standard approach is to create an overload for each type. Ein anderer Ansatz ist das Erstellen einer Überladung, die einen generischen Typ annimmt und diesen mit einem Delegaten in einen bestimmten Typ konvertiert.Another approach is to create an overload that will take a generic type and convert it to a specific type by using a delegate. Sie können auch beide Methoden kombinieren.You can also combine both approaches.

So erstellen Sie eine Überladung für jeden TypTo create an overload for each type

Sie können eine bestimmte Überladung für jeden Typ erstellen, den Sie unterstützen möchten.You can create a specific overload for each type that you want to support. Im folgenden Codebeispiel wird eine Überladung der Median-Methode für den integer-Typ veranschaulicht.The following code example shows an overload of the Median method for the integer type.

//int overload  

public static double Median(this IEnumerable<int> source)  
{  
    return (from num in source select (double)num).Median();  
}  

Sie können nun die Median-Überladungen für die integer- und double-Typen aufrufen, so wie im folgenden Code gezeigt:You can now call the Median overloads for both integer and double types, as shown in the following code:

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  
*/  

So erstellen Sie eine generische ÜberladungTo create a generic overload

Sie können auch eine Überladung erstellen, die eine Sequenz generischer Objekte akzeptiert.You can also create an overload that accepts a sequence of generic objects. Diese Überladung nimmt einen Delegaten als Parameter und verwendet ihn, um eine Sequenz von Objekten eines generischen Typs in einen bestimmten Typ zu konvertieren.This overload takes a delegate as a parameter and uses it to convert a sequence of objects of a generic type to a specific type.

Der folgende Code zeigt eine Überladung der Median-Methode, die den Func<T,TResult>-Delegaten als Parameter akzeptiert.The following code shows an overload of the Median method that takes the Func<T,TResult> delegate as a parameter. Dieser Delegat übernimmt ein Objekt des generischen Typs „T“ und gibt ein Objekt vom Typ double zurück.This delegate takes an object of generic type T and returns an object of type double.

// Generic overload.  

public static double Median<T>(this IEnumerable<T> numbers,  
                       Func<T, double> selector)  
{  
    return (from num in numbers select selector(num)).Median();  
}  

Sie können nun die Median-Methode für eine Sequenz von Objekten beliebigen Typs aufrufen.You can now call the Median method for a sequence of objects of any type. Wenn der Typ nicht über eine eigene Methodenüberladung verfügt, müssen sie einen Delegatenparameter übergeben.If the type does not have its own method overload, you have to pass a delegate parameter. In C# können Sie zu diesem Zweck einen Lambdaausdruck verwenden.In C#, you can use a lambda expression for this purpose. Wenn Sie die Aggregate- oder Group By-Klausel anstatt des Methodenaufrufs verwenden, können Sie auch einen beliebigen Wert oder Ausdruck übergeben, der im Bereich dieser Klausel vorhanden ist. Diese Methode ist nur in Visual Basic verfügbar.Also, in Visual Basic only, if you use the Aggregate or Group By clause instead of the method call, you can pass any value or expression that is in the scope this clause.

Der folgende Beispielcode veranschaulicht, wie eine Median-Methode für ein Array aus ganzen Zahlen und ein Array aus Zeichenfolgen aufgerufen wird.The following example code shows how to call the Median method for an array of integers and an array of strings. Für Zeichenfolgen wird der Median für die Längen der Zeichenfolgen im Array berechnet.For strings, the median for the lengths of strings in the array is calculated. Das Beispiel zeigt, wie der Delegatparameter Median an die Func<T,TResult>-Methode für jeden Fall übergeben wird.The example shows how to pass the Func<T,TResult> delegate parameter to the Median method for each case.

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  
*/  

Hinzufügen einer Methode, die eine Auflistung zurückgibtAdding a Method That Returns a Collection

Sie können die Schnittstelle IEnumerable<T> mit einer benutzerdefinierten Abfragemethode erweitern, die eine Sequenz von Werten zurückgibt.You can extend the IEnumerable<T> interface with a custom query method that returns a sequence of values. In diesem Fall muss die Methode eine Auflistung des Typs IEnumerable<T> zurückgeben.In this case, the method must return a collection of type IEnumerable<T>. Solche Methoden können verwendet werden, um Filter oder Datentransformationen auf eine Sequenz von Werten anzuwenden.Such methods can be used to apply filters or data transforms to a sequence of values.

Das folgende Beispiel zeigt, wie eine Erweiterungsmethode mit dem Namen AlternateElements erstellt wird, die jedes andere Element in einer Auflistung zurückgibt, beginnend mit dem ersten Element.The following example shows how to create an extension method named AlternateElements that returns every other element in a collection, starting from the first element.

// 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;  
}  

Sie können diese Erweiterungsmethode für jede aufzählbare Auflistung genau so aufrufen, wie Sie andere Methoden aus der Schnittstelle IEnumerable<T> aufrufen, so wie im folgenden Code dargestellt:You can call this extension method for any enumerable collection just as you would call other methods from the IEnumerable<T> interface, as shown in the following code:

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  
*/  

Siehe auchSee Also

IEnumerable<T>
ErweiterungsmethodenExtension Methods