Closures und erfasste Variablen
Sehen Sie, wie lokale Funktionen Zustände erfassen.
Closures und erfasste Variablen 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.
Closures über lokalen Zustand
Eine lokale Funktion oder ein Lambda-Ausdruck kann Variablen aus ihrer umgebenden Methode lesen und ändern. Dies wird als Erfassen bezeichnet; die Funktion und die von ihr erfassten Variablen bilden zusammen eine Closure.
Eine Variable erfassen
Die lokale Funktion verwendet factor direkt aus der umgebenden Methode. Sie erhält den Wert nicht als Parameter, sondern erfasst ihn aus dem umgebenden Gültigkeitsbereich.
using System;
public class Program
{
public static void Main()
{
int factor = 3;
int Scale(int n) => n * factor; // captures factor
Console.WriteLine(Scale(5));
Console.WriteLine(Scale(10));
}
}Erfasste Variablen sind lebende Referenzen
Eine Closure erfasst die Variable, nicht eine Momentaufnahme ihres Werts. Wenn sich die Variable nach der Definition der Funktion ändert, sieht die Funktion den neuen Wert.
using System;
public class Program
{
public static void Main()
{
int offset = 10;
int Add(int n) => n + offset;
Console.WriteLine(Add(1)); // 11
offset = 100;
Console.WriteLine(Add(1)); // 101 - sees updated offset
}
}Erfasste Variablen ändern
Eine Closure kann eine erfasste Variable schreiben; die Änderung ist dann auch in der umgebenden Methode sichtbar. Dadurch eignen sich Closures zum Aufbauen eines Zustands.
using System;
public class Program
{
public static void Main()
{
int count = 0;
void Tick() => count++;
Tick(); Tick(); Tick();
Console.WriteLine(count); // 3
}
}Eine Closure zurückgeben
Wenn Sie ein Lambda zurückgeben, das lokale Variablen erfasst hat, bestehen diese Variablen über die Methode hinaus fort. Der erfasste Zustand bleibt so lange erhalten wie das Delegate.
using System;
public class Program
{
static Func<int> MakeCounter()
{
int count = 0;
return () => ++count; // captures count
}
public static void Main()
{
var next = MakeCounter();
Console.WriteLine(next());
Console.WriteLine(next());
Console.WriteLine(next());
}
}Unabhängige Closures
Jeder Aufruf einer Factory erstellt eine neue Gruppe erfasster Variablen. Zwei auf diese Weise erstellte Zähler beeinflussen sich nicht gegenseitig.
using System;
public class Program
{
static Func<int> MakeCounter()
{
int count = 0;
return () => ++count;
}
public static void Main()
{
var a = MakeCounter();
var b = MakeCounter();
Console.WriteLine(a()); // 1
Console.WriteLine(a()); // 2
Console.WriteLine(b()); // 1 - separate state
}
}Die foreach-Capture-Korrektur
In modernem C# ist die Schleifenvariable einer foreach-Schleife für jede Iteration neu, sodass Closures den erwarteten Wert erfassen. Jedes Lambda unten merkt sich sein eigenes Element.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var actions = new List<Action>();
foreach (var i in new[] { 1, 2, 3 })
actions.Add(() => Console.WriteLine(i));
foreach (var act in actions) act(); // prints 1, 2, 3
}
}Erfassen in einer for-Schleife
Eine klassische Stolperfalle: Eine einzelne for-Schleifenvariable wird von allen Iterationen gemeinsam verwendet, sodass alle Closures ihren endgültigen Wert sehen. Kopieren Sie sie in eine lokale Variable pro Iteration, um unterschiedliche Werte zu erfassen.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var actions = new List<Action>();
for (int i = 0; i < 3; i++)
{
int copy = i; // fresh local each iteration
actions.Add(() => Console.WriteLine(copy));
}
foreach (var act in actions) act(); // prints 0, 1, 2
}
}Closures erfassen per Referenz, nicht per Wert
Da das Erfassen per Referenz erfolgt, wird eine Änderung des Originals nach dem Erfassen von der Closure beobachtet. Denken Sie daran, wenn der Zeitpunkt von Lese- und Schreibvorgängen eine Rolle spielt.
using System;
public class Program
{
public static void Main()
{
string message = "first";
Action print = () => Console.WriteLine(message);
print(); // first
message = "second";
print(); // second
}
}Praktische Anwendung: konfigurierbares Verhalten
Mit Closures können Sie kleine Funktionen erstellen, die bereits mit Kontext versehen sind. Hier erfasst eine Rabattfunktion einen Rabattsatz und erzeugt einen wiederverwendbaren, konfigurierten Rechner.
using System;
public class Program
{
static Func<double, double> MakeDiscount(double rate)
=> price => price * (1 - rate);
public static void Main()
{
var tenOff = MakeDiscount(0.10);
var halfOff = MakeDiscount(0.50);
Console.WriteLine(tenOff(100));
Console.WriteLine(halfOff(100));
}
}Probieren Sie es selbst aus
Erstellen Sie eine Zähler-Factory, deren zurückgegebene Closure einen privaten Zustand erhält, und erzeugen Sie daraus anschließend zwei unabhängige Zähler.
using System;
public class Program
{
static Func<int> MakeStepper(int step)
{
int current = 0;
return () => { current += step; return current; }; // captures current and step
}
public static void Main()
{
var byTwos = MakeStepper(2);
var byTens = MakeStepper(10);
Console.WriteLine(byTwos()); // 2
Console.WriteLine(byTwos()); // 4
Console.WriteLine(byTens()); // 10 - separate state
}
}Kurzer Check
Überlegen Sie, wie das Erfassen funktioniert.
Zusammenfassung
Closures erfassen Variablen aus dem umgebenden Gültigkeitsbereich per Referenz.
- Die Funktion sieht den aktuellen Wert der Variable einschließlich späterer Änderungen.
- Sie kann erfasste Variablen ändern und dadurch Zustand mit der Methode teilen.
- Zurückgegebene Closures halten ihre erfassten Variablen am Leben.
- Verwenden Sie in einer
for-Schleife eine lokale Variable pro Iteration, um unterschiedliche Werte zu erfassen.
Häufig gestellte Fragen
Ist die Lektion „Closures und erfasste Variablen“ kostenlos?
Ja — der vollständige Text von „Closures und erfasste Variablen“ 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 „Closures und erfasste Variablen“?
Sehen Sie, wie lokale Funktionen Zustände erfassen. 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 „Closures und erfasste Variablen“?
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
- Lokale Funktionen deklarieren
- Closures und erfasste Variablen
- Statische lokale Funktionen
- Lokale Funktionen versus Lambdas