CodeGym /Kurse /C# SELF /Kennenlernen anonymer Methoden (

Kennenlernen anonymer Methoden ( delegate)

C# SELF
Level 49 , Lektion 0
Verfügbar

1. Einführung

Wenn du programmierst, musst du manchmal eine einfache Aktion beschreiben, die nur einmal gebraucht wird und sonst nirgendwo. Dafür extra eine Methode zu erstellen ist wie mit dem Flugzeugbau-Montagehammer einen Nagel einzuschlagen. Viel einfacher: etwas Praktisches nehmen und das Problem "vor Ort" lösen.

Die anonyme Methode ist ein temporäres Code-Stück, das keinen Namen braucht, weil es genau dort verwendet wird, wo es entsteht. Sie:

  • Wird innerhalb einer anderen Methode deklariert.
  • Hat keinen Namen.
  • Wird normalerweise einmal verwendet — z.B. an einen Delegate übergeben oder auf ein Event abonniert.

Heutzutage verwendet man häufiger Lambda-Ausdrücke (Operator =>), aber das Verständnis anonymer Methoden hilft zu verstehen, wie Delegates und das Event-Modell in C# aufgebaut sind.

Wann sind anonyme Methoden praktisch?

  • Du musst schnell ein Stück Logik als Parameter übergeben, z.B. für Sortierung, Filterung, Events usw.
  • Es macht keinen Sinn, viele separate Methoden in einer Klasse für Einmal-Logik anzulegen.
  • Wenn der Code kompakt und gut lesbar sein soll: die "kleine Business-Logik" an einer Stelle.

Ein bisschen Geschichte

Die Möglichkeit, anonyme Methoden in C# zu erzeugen, kam erstmals in Version 2.0. Davor war die Arbeit mit Delegates umständlicher: man musste eine benannte Methode deklarieren, selbst wenn die Logik nur an einer Stelle benutzt wurde. Mit anonymen Methoden wurde vieles einfacher, und mit Lambda-Ausdrücken wurde die Idee noch knapper und eleganter.

2. Klassiker: Delegates und die übliche "benannte" Methode

Bevor wir anonyme Methoden kennenlernen, erinnern wir uns an die Standardweise, Verhalten über Delegates zu übergeben. Nehmen wir an, wir haben eine Anwendung "Buchdatenbank", in der wir Bücher nach unterschiedlichen Kriterien filtern wollen.

// Definieren des Delegates
public delegate bool BookFilter(Book book);

// Buch-Klasse
public class Book
{
    public string Title { get; set; }
    public int Year { get; set; }
}

Früher haben wir so geschrieben:

// Separater Filter-Funktion
public static bool IsClassic(Book b)
{
    return b.Year < 1970;
}

// Irgendwo im Anwendungscode
BookFilter filter = IsClassic;

Jedes Mal eine separate Methode anzulegen ist nicht immer praktisch. Und wenn es Dutzende Filter gibt?

3. Anonyme Methode: Minimalismus, gute Zusammenarbeit mit Delegates

Die anonyme Methode erlaubt es, den Filter-Code direkt dort zu definieren, wo er gebraucht wird:

BookFilter filter = delegate(Book b)
{
    return b.Year < 1970;
};

Das war's! Keine unnötigen Methoden, alles an Ort und Stelle. delegate fungiert hier als Deklaration einer namenlosen Funktion.

Allgemeine Syntax

delegate([Argumente])
{
    // Methodenrumpf
};

Beispiel eingebettet im Programm:

public class Book
{
    public string Title { get; set; }
    public int Year { get; set; }
}

public delegate bool BookFilter(Book book);

class Program
{
    static void Main()
    {
        Book[] books = {
            new Book { Title = "Master i Margarita", Year = 1967 },
            new Book { Title = "Clean Code", Year = 2008 }
        };

        // Anonymer Filter für Klassiker
        BookFilter filter = delegate(Book b)
        {
            return b.Year < 1970;
        };

        foreach (Book book in books)
        {
            if (filter(book)) // wir rufen die anonyme Funktion auf!
                Console.WriteLine($"{book.Title} — Klassiker!");
        }
    }
}

Ausgabe:

Master i Margarita — Klassiker!

4. Anonyme Methode mit verschiedenen Delegates

Anonyme Methoden funktionieren problemlos mit allen Delegates. Zum Beispiel mit den Standardtypen Action und Func<T, TResult>, die wir später detaillierter behandeln.

Action<string> sayHello = delegate(string name)
{
    Console.WriteLine($"Privet, {name}!");
};

sayHello("Mir"); // Privet, Mir!

Kurze Illustration: wie eine "Einmal"-anonyme Methode funktioniert

Man kann sich die anonyme Methode als temporären Arbeiter vorstellen: kommt für einen kurzen Job, erledigt ihn und verschwindet. Wir verbinden Arbeiter und Aufgabe über einen Delegate.

Func<int, int, int> sum = delegate (int a, int b) {
    return a + b;
};
Console.WriteLine(sum(5, 7)); // 12

Anwendung: Sortierung, Suche, Verarbeitung von Collections

Angenommen, wir haben eine Liste von Büchern, die wir nach Erscheinungsjahr sortieren wollen. Eine separate Methode für einen einmaligen Vergleich zu schreiben ist übertrieben.

var books = new List<Book>
{
    new Book { Title = "Master i Margarita", Year = 1967 },
    new Book { Title = "Clean Code", Year = 2008 }
};

books.Sort(delegate(Book a, Book b)
{
    return a.Year.CompareTo(b.Year);
});

foreach (var book in books)
    Console.WriteLine($"{book.Title} ({book.Year})");

5. Nützliche Feinheiten

Ist eine anonyme Methode das Gleiche wie ein Lambda-Ausdruck?

In modernem C# benutzt man häufiger Lambda-Ausdrücke (=>), und in der Regel gibt es wenig Unterschied, aber es bestehen einige grundsätzliche Unterschiede:

  • Lambdas sind kürzer und oft ausdrucksstärker.
  • Lambdas haben eindeutige Regeln für das Capturing von Variablen (dazu später mehr).
  • Anonyme Methoden kamen früher und tauchen manchmal in älterem Code auf.

So würde unser Beispiel mit einer Lambda aussehen:

BookFilter filter = b => b.Year < 1970;

Es ist trotzdem nützlich, sowohl die alte als auch die neue Syntax zu kennen — für Interviews, zum Lesen fremden Codes und für ein tieferes Verständnis von Delegates.

Anonyme Methoden mit und ohne Parameter

Wenn der Delegate keine Parameter hat, kann man ihn in einer Zeile schreiben:

Action printHello = delegate { Console.WriteLine("Privet!"); };
printHello(); // Privet!

Wenn Parameter vorhanden sind, geht das ebenfalls in einer Zeile:

Action<int> printSquare = delegate (int x) { Console.WriteLine(x * x); };
printSquare(6); // 36

Anonyme Methode und Lambda-Ausdruck

Anonyme Methode Lambda-Ausdruck
Syntax
delegate (...) {}
(args) => {}
Variablen-Capture Ja Ja
Beliebtheit Wird selten verwendet Standard
Rückgabewert Kann/muss Kann/muss
Mehrzeiligkeit Geht Geht

6. Anonyme Methoden — Kleinigkeiten und Nutzungshinweise

Capture lokaler Variablen
Anonyme Methoden können Variablen aus der umgebenden Methode verwenden — dieser Mechanismus heißt "Closure". Zum Beispiel:

int minYear = 1970;

BookFilter filter = delegate(Book book)
{
    return book.Year < minYear;
};

Console.WriteLine(filter(new Book { Title = "Test", Year = 1960 })); // True

Wenn du später minYear änderst, wird der Filter den neuen Wert verwenden!

Parameter weglassen
Wenn keine Parameter benötigt werden:

Action sayHi = delegate { Console.WriteLine("Hi!"); };

Übergabe von null
Wenn einem Delegate keine Methode zugewiesen wurde (z.B. keine anonyme Methode), ist sein Wert null, und ein Versuch, ihn aufzurufen, führt zu einer NullReferenceException. Vorsicht also.

Mehrzeilige Blöcke
Eine anonyme Methode kann einen vollständigen Code-Block enthalten, mit Bedingungen, Schleifen und weiteren Aufrufen:

Action manyThings = delegate
{
    Console.WriteLine("Nachalo!");
    for (int i = 0; i < 3; i++)
        Console.WriteLine(i);
    Console.WriteLine("Zakonchili!");
};
manyThings();

7. Typische Fehler und Besonderheiten

Manchmal verwechseln Entwickler den Gültigkeitsbereich von Variablen: das Capturing von Schleifenvariablen oder verschachtelten Methoden kann zu unerwarteten Ergebnissen führen.

List<Action> actions = new List<Action>();
for (int i = 0; i < 3; i++)
{
    actions.Add(delegate { Console.WriteLine(i); });
}
foreach (var action in actions) action(); // 3 3 3 — Überraschung!

Der Grund ist, dass die anonyme Methode die Variable i "sieht" — wenn die Schleife fertig ist, ist i 3. Alle Methoden drucken dasselbe. Für korrektes Verhalten fange die Variable so:

for (int i = 0; i < 3; i++)
{
    int current = i;
    actions.Add(delegate { Console.WriteLine(current); });
}
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION