Lokale functies

Kies een lokale functie als u helperlogica een beschrijvende naam wilt geven en slechts één member die helper nodig heeft. Vergeleken met een methode op het omvattende type, vertelt een lokale functie lezers dat de helper deel uitmaakt van deze bewerking. Met de naam kunnen lezers de hoofdlijn volgen voordat ze de details inspecteren.

Tip

In dit artikel leert u hoe u lokale functies praktisch gebruikt voor ontwikkelaars die weten hoe ze methoden kunnen schrijven. Zie Declaraties van lokale functies voor informatie over declaraties en diagnostische regels.

Een lokale functie is een benoemde functie die in een ander lid is gedeclareerd, zoals een methode of constructor. De naam is alleen zichtbaar binnen die member.

De volgende shape declareert en roept een lokale functie aan:

string CreateMessage(string name)
{
    return AddGreeting(name);

    string AddGreeting(string value) => $"Hello, {value}!";
}

AddGreeting blijft binnen CreateMessage. Andere leden van het type kunnen het niet aanroepen.

Houd helperlogica in de buurt van de aanroeper

Met lokale functies kan de hoofdstroom aangeven wat er gebeurt terwijl helperfuncties afzonderlijke stappen uitleggen. In het volgende voorbeeld wordt een leesplan gemaakt. Er wordt een lokale functie gebruikt om de opdracht van één week tegelijk toe te voegen.

IReadOnlyList<ReadingWeek> plan =
    CreateReadingPlan("The Long Way Home", chapterCount: 10, chaptersPerWeek: 3);

foreach (ReadingWeek week in plan)
{
    Console.WriteLine(
        $"Week {week.Number}: {week.BookTitle}, chapters {week.FirstChapter}-{week.LastChapter}");
}

static IReadOnlyList<ReadingWeek> CreateReadingPlan(
    string bookTitle,
    int chapterCount,
    int chaptersPerWeek)
{
    var plan = new List<ReadingWeek>();
    AddWeek(firstChapter: 1);
    return plan;

    void AddWeek(int firstChapter)
    {
        if (firstChapter > chapterCount)
        {
            return;
        }

        int lastChapter = Math.Min(
            firstChapter + chaptersPerWeek - 1,
            chapterCount);

        plan.Add(new ReadingWeek(
            plan.Count + 1,
            bookTitle,
            firstChapter,
            lastChapter));

        AddWeek(lastChapter + 1);
    }
}

Een ReadingWeek registreert een weeknummer en het bereik van hoofdstukken die voor die week zijn toegewezen. AddWeek behoort alleen tot CreateReadingPlan, dus communiceert de lokale scope die relatie.

U kunt een lokale functie declareren vóór of na de instructies die deze aanroepen. Plaats deze waar lezers het hoofdverloop kunnen volgen zonder context te verliezen.

Parameters gebruiken of lokale toestand vastleggen

Een niet-statische lokale functie kan parameters en lokale variabelen van het bijbehorende lid gebruiken. Dit gebruik wordt vastleggen genoemd. In het voorbeeld AddWeek van het leesplan wordt het volgende vastgelegd:

  • bookTitle, chapterCounten chaptersPerWeek van de CreateReadingPlan parameters.
  • plan van een lokale variabele.

Vastleggen is handig wanneer de helper natuurlijk deel uitmaakt van de omringende bewerking. Houd het aantal vastgelegde waarden beperkt en duidelijk. Als de helper alle gegevens kan ontvangen via parameters, kunt u een static lokale functie overwegen:

static int LastChapter(int firstChapter, int chaptersPerWeek, int chapterCount) =>
    Math.Min(firstChapter + chaptersPerWeek - 1, chapterCount);

Een statische lokale functie kan geen lokale variabelen, parameters of instantiestatus van het bijbehorende lid vastleggen. De parameters maken de opgegeven gegevens expliciet, terwijl capture een helper de context van de bijbehorende bewerking laat gebruiken.

Gebruik recursie wanneer het probleem zichzelf herhaalt

Recursie treedt op wanneer een functie zichzelf aanroept met een kleiner deel van het probleem. AddWeek in het voorbeeld voegt één week toe en roept zichzelf vervolgens aan met het eerste hoofdstuk voor de volgende week.

Elke recursieve functie heeft een voorwaarde nodig waarmee de aanroepen worden gestopt. AddWeek stopt wanneer firstChapter groter is dan chapterCount:

if (firstChapter > chapterCount)
{
    return;
}

Lokale functies werken goed voor recursie omdat hun namen binnen het bereik vallen van het betreffende lid. Geef de voorkeur aan een lus als die het herhaalde werk directer weergeeft. Kies recursie wanneer de recursieve structuur het algoritme gemakkelijker te begrijpen maakt.

Een lokale functie of lambda-expressie kiezen

Lokale functies en lambda-expressies kunnen beide omringende variabelen gebruiken, maar ze communiceren verschillende intenties:

Kiezen When
Lokale functie De helper heeft baat bij een naam, heeft verschillende instructies, heeft recursie nodig of wordt aangeroepen vanaf meer dan één plaats in het omvattende lid.
Lambda-expressie U geeft korte functionaliteit rechtstreeks door aan een andere methode of slaat die op in een delegatevariabele.

De volgende code maakt gebruik van beide vormen:

static IEnumerable<string> DescribeShortWeeks(
    IEnumerable<ReadingWeek> plan,
    int maximumChapters)
{
    return plan
        .Where(IsShortWeek)
        .Select(week => $"Week {week.Number}: {week.FirstChapter}-{week.LastChapter}");

    bool IsShortWeek(ReadingWeek week) =>
        week.LastChapter - week.FirstChapter + 1 <= maximumChapters;
}

Console.WriteLine("Short weeks:");
foreach (string description in DescribeShortWeeks(plan, maximumChapters: 2))
{
    Console.WriteLine(description);
}

IsShortWeek geeft de aan Where doorgegeven regel een beschrijvende naam. De lambda die is doorgegeven aan Select voert één korte transformatie uit op het moment van gebruik. Beide vormen leveren hier gedrag aan een andere methode. Een lokale functie kan ook een helper zijn die u rechtstreeks aanroept, zoals AddWeek dat is in het voorbeeld van het leesplan.

Gebruik een reguliere methode in plaats van een lokale functie wanneer meerdere members de helper nodig hebben. Gebruik in plaats daarvan een lambda als het gedrag kort is en het doel ervan duidelijk is uit de ontvangende methode.

Lokale functies kunnen ook iteratorfuncties zijn die yield return bevatten. Zie Iterators voor dat gebruik.

Zie ook