C# Academy · Les

Semantiek van luie evaluatie

Krijg inzicht in uitgestelde uitvoering van iterators.

Les 3 van 413 stappen

Semantiek van luie evaluatie is een gratis C# Academy-les op CoddyKit. Dit is les 3 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject C# Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus C# Academy bevat in totaal 4 lessen.

Uitgestelde uitvoering

Iterators en LINQ-query's gebruiken uitgestelde uitvoering: het definiëren van de query doet vrijwel niets. Het werk gebeurt pas wanneer je het resultaat daadwerkelijk opsomt, item voor item.

Er wordt niets uitgevoerd totdat je opsomt

Het aanroepen van een iteratormethode voert de bijbehorende hoofdtekst niet uit. De uitvoering begint pas wanneer een foreach (of een andere verbruiker) de eerste waarde opvraagt.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Numbers()
    {
        Console.WriteLine("-- iterator body started --");
        yield return 1;
        yield return 2;
    }

    public static void Main()
    {
        var seq = Numbers();
        Console.WriteLine("query created, body not run yet");
        foreach (var n in seq) Console.WriteLine(n);
    }
}

Waarden worden één voor één geproduceerd

Elke iteratie voert precies genoeg van de iterator uit om de volgende waarde te produceren. Dit model, waarbij waarden worden opgevraagd, houdt het geheugengebruik laag, zelfs voor enorme reeksen.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Trace()
    {
        for (int i = 1; i <= 3; i++)
        {
            Console.WriteLine("producing " + i);
            yield return i;
        }
    }

    public static void Main()
    {
        foreach (var n in Trace())
            Console.WriteLine("consumed " + n);
    }
}

Opnieuw opsommen voert opnieuw uit

Een uitgestelde reeks heeft geen opgeslagen resultaat. Als je de reeks twee keer opsomt, wordt de iterator twee keer uitgevoerd. Dat is belangrijk als de bron verandert of het werk veel tijd kost.

using System;
using System.Collections.Generic;

public class Program
{
    static int _calls = 0;
    static IEnumerable<int> Counter()
    {
        _calls++;
        yield return _calls;
    }

    public static void Main()
    {
        var seq = Counter();
        foreach (var n in seq) Console.WriteLine(n);
        foreach (var n in seq) Console.WriteLine(n);
        Console.WriteLine("total runs: " + _calls);
    }
}

De actuele toestand vastleggen

Omdat de uitvoering is uitgesteld, leest een iterator de bron tijdens het opsommen en niet tijdens het definiëren. Wijzigingen die je na het definiëren van de query aanbrengt, zijn zichtbaar.

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var list = new List<int> { 1, 2 };
        IEnumerable<int> doubled = Double(list);
        list.Add(3); // added before enumeration
        foreach (var n in doubled) Console.WriteLine(n);
    }

    static IEnumerable<int> Double(IEnumerable<int> nums)
    {
        foreach (var n in nums) yield return n * 2;
    }
}

Onmiddellijke uitvoering afdwingen

Als je een momentopname van de resultaten wilt maken, materialiseer je de reeks met ToList() of ToArray(). Hierdoor wordt de iterator één keer uitgevoerd en worden de waarden opgeslagen, onafhankelijk van latere wijzigingen in de bron.

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

public class Program
{
    public static void Main()
    {
        var list = new List<int> { 1, 2 };
        List<int> snapshot = Double(list).ToList(); // executed now
        list.Add(99);
        Console.WriteLine(string.Join(",", snapshot));
    }

    static IEnumerable<int> Double(IEnumerable<int> nums)
    {
        foreach (var n in nums) yield return n * 2;
    }
}

Vroegtijdig stoppen bespaart werk

Omdat verbruikers waarden lui opvragen, kan een bewerking zoals het zoeken naar de eerste overeenkomst vroegtijdig stoppen. De producent berekent nooit waarden waar niet om wordt gevraagd.

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

public class Program
{
    static IEnumerable<int> Numbers()
    {
        for (int i = 1; ; i++)
        {
            Console.WriteLine("checking " + i);
            yield return i;
        }
    }

    public static void Main()
    {
        int firstBig = Numbers().First(n => n > 3);
        Console.WriteLine("found " + firstBig);
    }
}

Uitgestelde uitzonderingen

Een uitzondering in een iterator wordt niet gegenereerd wanneer de methode wordt aangeroepen, maar wanneer het opsommen de regel bereikt die de fout veroorzaakt. Dat kan je verrassen als je verwacht dat invoer vooraf wordt gevalideerd.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Risky(int divisor)
    {
        yield return 10 / divisor; // throws only during enumeration
    }

    public static void Main()
    {
        var seq = Risky(0);
        Console.WriteLine("no error yet");
        try { foreach (var n in seq) Console.WriteLine(n); }
        catch (DivideByZeroException) { Console.WriteLine("caught during enumeration"); }
    }
}

Luie pijplijnen zijn eenvoudig te combineren

Het koppelen van luie operatoren voert ze niet steeds opnieuw uit. Elke waarde stroomt op aanvraag één keer door de volledige pijplijn. Dat is efficiënt en bespaart geheugen.

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

public class Program
{
    public static void Main()
    {
        var result = Enumerable.Range(1, 1000000)
            .Where(n => n % 2 == 0)
            .Select(n => n * n)
            .Take(3);
        foreach (var n in result) Console.WriteLine(n);
    }
}

Wanneer je moet materialiseren

Materialiseer wanneer je meerdere keren gaat opsommen, wanneer de bron kan veranderen of wanneer je resultaten moet vastleggen voordat je een resource opruimt. Blijf anders lui om geheugen en werk te besparen.

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

public class Program
{
    public static void Main()
    {
        var evens = Enumerable.Range(1, 10).Where(n => n % 2 == 0).ToList();
        // Safe to enumerate many times now
        Console.WriteLine("count: " + evens.Count);
        Console.WriteLine("sum: " + evens.Sum());
    }
}

Probeer het zelf

Bekijk uitgestelde uitvoering rechtstreeks: er wordt een query gedefinieerd, de bron wordt gewijzigd en pas tijdens het opsommen worden de wijzigingen zichtbaar in de resultaten.

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

public class Program
{
    public static void Main()
    {
        var source = new List<int> { 1, 2, 3 };
        var query = source.Where(n => n > 1); // not executed yet
        source.Add(10);
        source.Remove(2);
        // Executes now, reflecting all changes
        Console.WriteLine(string.Join(", ", query));
    }
}

Korte controle

Redeneer over uitgestelde uitvoering.

Samenvatting

Luie (uitgestelde) evaluatie voert een reeks pas uit wanneer deze wordt opgesomd.

  • Het definiëren van een query doet niets; het verbruiken ervan wel.
  • Opnieuw opsommen voert de iterator opnieuw uit.
  • Bronnen worden tijdens het opsommen gelezen, dus latere wijzigingen zijn zichtbaar.
  • Uitzonderingen worden tijdens het opsommen zichtbaar.
  • Gebruik ToList()/ToArray() om indien nodig te materialiseren.
Gratis beginnen

Leer C# met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
93
Lessen
346

Veelgestelde vragen

Is de les “Semantiek van luie evaluatie” gratis?

Ja — de volledige tekst van “Semantiek van luie evaluatie” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus C# Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus C# Academy bevat in totaal 4 lessen.

Wat leer ik in “Semantiek van luie evaluatie”?

Krijg inzicht in uitgestelde uitvoering van iterators. Je oefent met C# Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met C# Academy te beginnen?

Ervaring vooraf is niet nodig. C# Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.

Hoe lang duurt de les “Semantiek van luie evaluatie”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over C# Academy?

Ja. Elke les over C# Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Iteratormethoden met yield return
  2. yield break en vroegtijdige beëindiging
  3. Semantiek van luie evaluatie
  4. Aangepaste enumerables
← Terug naar C# Academy