0Pricing
C# Academy · Lektion

Interfaces und Generics erweitern

Fügen Sie vielen Typen gleichzeitig Verhalten hinzu.

Interfaces und Generics erweitern ist eine kostenlose C# Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des C# Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der C# Academy-Kurs umfasst insgesamt 4 Lektionen.

Interfaces erweitern

Sie können eine Erweiterungsmethode schreiben, deren this-Parameter ein Interface ist. Jeder Typ, der dieses Interface implementiert, erhält die Methode sofort. Genau so fügt LINQ Dutzende Methoden zu IEnumerable<T> hinzu.

Eine generische Erweiterung für IEnumerable

Wenn Sie die Methode für T generisch gestalten und IEnumerable<T> erweitern, funktioniert die Hilfsmethode für jede Sequenz: Listen, Arrays, Abfrageergebnisse und vieles mehr.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static bool IsEmpty<T>(this IEnumerable<T> source)
    {
        foreach (var item in source) return false;
        return true;
    }
}

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 1, 2, 3 };
        Console.WriteLine(nums.IsEmpty());
        Console.WriteLine(new int[0].IsEmpty());
    }
}

Durchlaufen der Sequenz

Innerhalb der Erweiterungsmethode behandeln Sie den Parameter wie jedes andere IEnumerable<T>. Hier berechnen wir eine Summe, ohne auf LINQ zurückzugreifen.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static int SumValues(this IEnumerable<int> source)
    {
        int total = 0;
        foreach (var n in source) total += n;
        return total;
    }
}

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 10, 20, 30 };
        Console.WriteLine(nums.SumValues());
    }
}

Eine neue Sequenz zurückgeben

Erweiterungsmethoden können auch Sequenzen zurückgeben. Zusammen mit yield return werden sie zu verzögert ausgewerteten Operatoren im LINQ-Stil.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static IEnumerable<T> EveryOther<T>(this IEnumerable<T> source)
    {
        bool take = true;
        foreach (var item in source)
        {
            if (take) yield return item;
            take = !take;
        }
    }
}

public class Program
{
    public static void Main()
    {
        var letters = new List<string> { "a", "b", "c", "d", "e" };
        foreach (var l in letters.EveryOther())
            Console.WriteLine(l);
    }
}

Einschränkungen für generische Typen

Sie können den generischen Parameter so einschränken, dass bestimmte Fähigkeiten erforderlich sind. Mit where T : IComparable<T> können wir hier Elemente vergleichen, um ein Maximum zu finden.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static T MaxItem<T>(this IEnumerable<T> source) where T : IComparable<T>
    {
        bool started = false;
        T best = default;
        foreach (var item in source)
        {
            if (!started || item.CompareTo(best) > 0) { best = item; started = true; }
        }
        return best;
    }
}

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 3, 9, 1, 7 };
        Console.WriteLine(nums.MaxItem());
    }
}

Eine eigene Schnittstelle erweitern

Auch Ihre eigenen Schnittstellen profitieren davon. Definieren Sie eine Schnittstelle und fügen Sie ihr über Erweiterungsmethoden gemeinsames Verhalten hinzu, statt es in jedem Implementierer zu duplizieren.

using System;

public interface INamed { string Name { get; } }

public class Dog : INamed { public string Name => "Rex"; }

public static class NamedExtensions
{
    public static string Greeting(this INamed n) => "Hello, " + n.Name;
}

public class Program
{
    public static void Main()
    {
        var d = new Dog();
        Console.WriteLine(d.Greeting());
    }
}

Mehrere Typparameter

Erweiterungsmethoden können über mehrere Typparameter generisch sein. Dieser Projektionshelfer bildet eine Sequenz mithilfe einer Funktion ab, ähnlich wie LINQ Select.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static IEnumerable<TResult> Map<TSource, TResult>(
        this IEnumerable<TSource> source, Func<TSource, TResult> f)
    {
        foreach (var item in source) yield return f(item);
    }
}

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 1, 2, 3 };
        foreach (var s in nums.Map(n => "#" + n))
            Console.WriteLine(s);
    }
}

Mit integriertem LINQ kombinieren

Ihre Erweiterungsmethoden funktionieren neben LINQ. Sie können Ihren eigenen Operator in einer einzigen Fluent-Pipeline mit Standardoperatoren verketten.

using System;
using System.Collections.Generic;
using System.Linq;

public static class EnumerableExtensions
{
    public static IEnumerable<T> EveryOther<T>(this IEnumerable<T> source)
    {
        bool take = true;
        foreach (var item in source) { if (take) yield return item; take = !take; }
    }
}

public class Program
{
    public static void Main()
    {
        var nums = Enumerable.Range(1, 10);
        var result = nums.Where(n => n > 2).EveryOther().ToList();
        Console.WriteLine(string.Join(", ", result));
    }
}

Die Erweiterung von IEnumerable erreicht viele Typen

Da Arrays, Listen, Wörterbücher, Hashsets und Abfrageergebnisse alle IEnumerable<T> implementieren, deckt eine einzige Erweiterungsmethode sie alle ab.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static int CountItems<T>(this IEnumerable<T> source)
    {
        int n = 0;
        foreach (var item in source) n++;
        return n;
    }
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new[] { 1, 2, 3 }.CountItems());
        Console.WriteLine(new HashSet<string> { "a", "b" }.CountItems());
    }
}

Warum dieses Muster skalierbar ist

Schnittstellenerweiterungen bieten Ihnen polymorphe Hilfsmethoden ohne Vererbung. Schreiben Sie die Logik einmal gegen die Schnittstelle, und jeder aktuelle und zukünftige Implementierer erhält sie automatisch.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static string JoinWith<T>(this IEnumerable<T> source, string sep)
    {
        return string.Join(sep, source);
    }
}

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 1, 2, 3 };
        Console.WriteLine(nums.JoinWith(" -> "));
    }
}

Probieren Sie es selbst aus

Erstellen Sie einen kleinen generischen Operator für IEnumerable<T> und verketten Sie ihn mit LINQ. Beachten Sie, dass er mit jedem Sequenztyp funktioniert.

using System;
using System.Collections.Generic;
using System.Linq;

public static class EnumerableExtensions
{
    public static IEnumerable<T> WithoutDuplicatesByKey<T, TKey>(
        this IEnumerable<T> source, Func<T, TKey> keySelector)
    {
        var seen = new HashSet<TKey>();
        foreach (var item in source)
            if (seen.Add(keySelector(item))) yield return item;
    }
}

public class Program
{
    public static void Main()
    {
        var words = new[] { "apple", "avocado", "banana", "cherry", "blueberry" };
        var firstPerLetter = words.WithoutDuplicatesByKey(w => w[0]);
        Console.WriteLine(string.Join(", ", firstPerLetter));
    }
}

Kurze Überprüfung

Überlegen Sie, wie Erweiterungsmethoden im LINQ-Stil deklariert werden.

Zusammenfassung

Die Erweiterung von Schnittstellen, insbesondere von IEnumerable<T>, bildet die Grundlage der Programmierung im LINQ-Stil.

  • Machen Sie die Methode generisch und verwenden Sie die Schnittstelle als this-Typ.
  • Verwenden Sie yield return, um verzögert ausgewertete Operatoren zu erstellen.
  • Verwenden Sie where-Einschränkungen, um Fähigkeiten wie IComparable<T> vorauszusetzen.
  • Eine Schnittstellenerweiterung deckt alle Implementierer ab, auch zukünftige.

Häufig gestellte Fragen

Ist die Lektion „Interfaces und Generics erweitern“ kostenlos?

Ja — der vollständige Text von „Interfaces und Generics erweitern“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des C# Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der C# Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Interfaces und Generics erweitern“?

Fügen Sie vielen Typen gleichzeitig Verhalten hinzu. Du übst C# Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um C# Academy zu starten?

Keine Vorkenntnisse erforderlich. C# Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „Interfaces und Generics erweitern“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser C# Academy-Lektion Code schreiben und ausführen?

Ja. Jede C# Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Extension Methods definieren
  2. Interfaces und Generics erweitern
  3. Auflösung von Extension Methods
  4. Gute Extensions entwerfen
← Zurück zu C# Academy