Lokální funkce

Zvolte místní funkci, pokud chcete pomocné logice poskytnout popisný název a tento pomocník je potřeba jen pro jeden člen. Ve srovnání s metodou v obsahujícím typu říká místní funkce čtenářům, že pomocná rutina patří k této operaci. Jeho název umožňuje čtenářům sledovat hlavní tok před kontrolou podrobností.

Tip

V tomto článku se naučíte praktické použití místních funkcí pro vývojáře, kteří vědí, jak psát metody. Podrobnosti o deklaraci a diagnostická pravidla najdete v tématu Deklarace místních funkcí.

Místní funkce je pojmenovaná funkce deklarovaná uvnitř jiného členu, jako je metoda nebo konstruktor. Jeho název je v rozsahu platnosti pouze v rámci tohoto člena.

Následující tvar deklaruje a volá místní funkci:

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

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

AddGreeting zůstává uvnitř CreateMessage. Ostatní členové typu ho nemůžou volat.

Pomocnou logiku ponechte blízko místa volání

Místní funkce umožňují hlavnímu toku popsat, co se stane, zatímco pomocné funkce vysvětlují jednotlivé kroky. Následující příklad vytvoří plán čtení. Používá lokální funkci k přidávání přiřazení po jednom týdnu.

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

ReadingWeek zaznamenává číslo týdne a rozsah kapitol přiřazených pro daný týden. AddWeek patří pouze do CreateReadingPlan, takže jeho místní rozsah vyjadřuje tento vztah.

Místní funkci můžete deklarovat před nebo za příkazy, které ji volají. Umístěte ho tam, kde můžou čtenáři sledovat hlavní tok bez ztráty kontextu.

Použijte parametry nebo zachyťte místní stav

Nestatická místní funkce může používat parametry a místní proměnné ze svého nadřazeného člena. Toto použití se nazývá zachycení. V příkladu AddWeek plánu čtení zachycuje:

  • bookTitle, chapterCount a chaptersPerWeek z parametrů CreateReadingPlan.
  • plan z místní proměnné.

Capture je užitečné, když pomocná rutina přirozeně patří do okolní operace. Udržujte počet zachycených hodnot na minimu a jejich význam zřejmý. Pokud pomocná rutina může přijímat všechna data prostřednictvím parametrů, zvažte static místní funkci:

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

Statická místní funkce nemůže zachytit místní proměnné, parametry nebo stav instance z obsahujícího členu. Jeho parametry činí zadaná data explicitními, zatímco capture umožňuje pomocné funkci použít kontext operace, která ji obsahuje.

Použijte rekurzi, když se problém opakuje.

Rekurze nastane, když funkce volá sama sebe s menší částí problému. AddWeek v příkladu přidá jeden týden a pak se rekurzivně zavolá s první kapitolou pro příští týden.

Každá rekurzivní funkce potřebuje podmínku, která zastaví volání. AddWeek se zastaví, když firstChapter překročí chapterCount:

if (firstChapter > chapterCount)
{
    return;
}

Místní funkce dobře fungují pro rekurzi, protože jejich názvy jsou v oboru platnosti v rámci celého nadřazeného členu. Preferujte smyčku, když vyjadřuje opakovanou práci přímo. Zvolte rekurzi, když rekurzivní struktura usnadňuje pochopení algoritmu.

Zvolte místní funkci nebo výraz lambda

Místní funkce i výrazy lambda můžou používat okolní proměnné, ale vyjadřují jiný záměr:

Zvolit Když
Místní funkce Pomocnou rutinu je vhodné pojmenovat, obsahuje několik příkazů, vyžaduje rekurzi nebo je volána z více než jednoho místa v obsahujícím členu.
Výraz lambda Krátký blok kódu předáte přímo jiné metodě nebo ho uložíte do proměnné delegáta.

Následující kód používá obě formy:

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 dává pravidlu předanému do Where popisný název. Lambda předaná do Select provádí jednu krátkou transformaci v okamžiku použití. Oba způsoby zde dodávají chování jiné metodě. Místní funkce může být také pomocná rutina, kterou voláte přímo, jak je tomu u AddWeek v příkladu plánu čtení.

Místo místní funkce používejte běžnou metodu, když pomocnou rutinu potřebuje několik členů třídy. Místo toho použijte lambdu, pokud je chování krátké a jeho účel je jasný z přijímající metody.

Místní funkce mohou být také iterátorové funkce, které obsahují yield return. Viz Iterátory.

Viz také