0Pricing
C# Academy · Leçon

Fermetures et variables capturées

Observez comment les fonctions locales capturent l’état.

Fermetures et variables capturées est une leçon C# Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C# Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C# Academy comprend 4 leçons au total.

Fermetures sur l'état local

Une fonction locale (ou une lambda) peut lire et modifier des variables de sa méthode englobante. On parle alors de capture, et la fonction ainsi que les variables capturées forment une fermeture.

Capturer une variable

La fonction locale utilise directement factor de la méthode englobante. Elle ne le reçoit pas comme paramètre ; elle le capture depuis la portée environnante.

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

Les variables capturées sont des références vivantes

Une fermeture capture la variable, et non un instantané de sa valeur. Si la variable change après la définition de la fonction, celle-ci voit la nouvelle valeur.

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

Modifier des variables capturées

Une fermeture peut écrire dans une variable capturée, et la modification est également visible dans la méthode englobante. Les fermetures sont ainsi utiles pour accumuler un état.

using System;

public class Program
{
    public static void Main()
    {
        int count = 0;
        void Tick() => count++;

        Tick(); Tick(); Tick();
        Console.WriteLine(count); // 3
    }
}

Retourner une fermeture

Lorsque vous retournez une lambda qui a capturé des variables locales, ces variables continuent d'exister après la fin de la méthode. L'état capturé subsiste aussi longtemps que le délégué.

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

Fermetures indépendantes

Chaque appel à une fabrique crée un nouvel ensemble de variables capturées. Deux compteurs construits de cette manière n'interfèrent pas l'un avec l'autre.

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

La correction de la capture dans foreach

En C# moderne, la variable de boucle foreach est nouvelle à chaque itération ; les fermetures capturent donc la valeur attendue. Chaque lambda ci-dessous mémorise son propre élément.

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

Capturer dans une boucle for

Un piège classique : une seule variable de boucle for est partagée entre les itérations, si bien que toutes les fermetures voient sa valeur finale. Copiez-la dans une variable locale propre à chaque itération pour capturer des valeurs distinctes.

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

Les fermetures capturent par référence, pas par valeur

Comme la capture se fait par référence, toute modification de l'original après la capture est observée par la fermeture. Gardez-le à l'esprit lorsque le moment des lectures et des écritures est important.

using System;

public class Program
{
    public static void Main()
    {
        string message = "first";
        Action print = () => Console.WriteLine(message);

        print();          // first
        message = "second";
        print();          // second
    }
}

Utilisation pratique : comportement configurable

Les fermetures permettent de créer de petites fonctions préchargées avec un contexte. Ici, une fonction de remise capture un taux et produit une calculatrice réutilisable et configurée.

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

À vous de jouer

Créez une fabrique de compteurs dont la fermeture retournée conserve un état privé, puis créez deux compteurs indépendants à partir de cette fabrique.

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

Vérification rapide

Raisonnez sur le fonctionnement de la capture.

Récapitulatif

Les fermetures capturent les variables englobantes par référence.

  • La fonction voit la valeur actuelle de la variable, y compris les modifications ultérieures.
  • Elle peut modifier les variables capturées et partager un état avec la méthode.
  • Les fermetures retournées maintiennent leurs variables capturées en vie.
  • Utilisez une variable locale propre à chaque itération dans une boucle for pour capturer des valeurs distinctes.

Questions Fréquemment Posées

La leçon « Fermetures et variables capturées » est-elle gratuite ?

Oui — le texte complet de « Fermetures et variables capturées » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C# Academy, passe à CoddyKit PRO. Le cours C# Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Fermetures et variables capturées » ?

Observez comment les fonctions locales capturent l’état. Tu pratiques C# Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer C# Academy ?

Aucune expérience préalable n'est requise. C# Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Fermetures et variables capturées » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon C# Academy ?

Oui. Chaque leçon C# Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Déclarer des fonctions locales
  2. Fermetures et variables capturées
  3. Fonctions locales statiques
  4. Fonctions locales ou lambdas
← Retour à C# Academy