Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Scegliere una funzione locale quando si vuole assegnare alla logica helper un nome descrittivo e un solo membro necessita di tale helper. Rispetto a un metodo sul tipo contenitore, una funzione locale indica ai lettori che l'helper appartiene a questa operazione. Il nome consente ai lettori di seguire il flusso principale prima di esaminare i dettagli.
Tip
Questo articolo illustra l'uso pratico delle funzioni locali per gli sviluppatori che sanno come scrivere metodi. Per dettagli sulle dichiarazioni e sulle regole di diagnostica, vedere Dichiarazioni di funzioni locali.
Una funzione locale è una funzione denominata dichiarata all'interno di un altro membro, ad esempio un metodo o un costruttore. Il nome è visibile solo all'interno di tale membro.
Lo shape seguente dichiara e chiama una funzione locale:
string CreateMessage(string name)
{
return AddGreeting(name);
string AddGreeting(string value) => $"Hello, {value}!";
}
AddGreeting rimane all'interno di CreateMessage. Altri membri del tipo non possono chiamarlo.
Mantieni la logica helper vicino al relativo punto di chiamata
Le funzioni locali consentono al flusso principale di indicare cosa accade, mentre le funzioni helper illustrano i singoli passaggi. Nell'esempio seguente viene creato un piano di lettura. Usa una funzione locale per aggiungere un'assegnazione di una settimana alla volta.
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);
}
}
Un record ReadingWeek registra un numero di settimana e l'intervallo di capitoli assegnati per quella settimana.
AddWeek appartiene solo a CreateReadingPlan, quindi il suo ambito locale comunica tale relazione.
È possibile dichiarare una funzione locale prima o dopo le istruzioni che la chiamano. Posizionalo dove i lettori possono seguire il flusso principale senza perdere contesto.
Usare parametri o acquisire lo stato locale
Una funzione locale non statica può usare parametri e variabili locali del membro che la contiene. Questo uso viene chiamato capture. Nell'esempio di piano di lettura, AddWeek acquisisce:
-
bookTitle,chapterCountechaptersPerWeekdaiCreateReadingPlanparametri . -
planda una variabile locale.
Capture è utile quando l'helper appartiene naturalmente all'operazione circostante. Mantieni pochi e chiari i valori acquisiti. Se l'helper può ricevere tutti i dati tramite parametri, considerare una static funzione locale:
static int LastChapter(int firstChapter, int chaptersPerWeek, int chapterCount) =>
Math.Min(firstChapter + chaptersPerWeek - 1, chapterCount);
Una funzione locale statica non può acquisire variabili, parametri o stato dell'istanza locali dal membro contenitore. I relativi parametri rendono espliciti i dati forniti, mentre capture consente a un helper di usare il contesto dell'operazione contenitore.
Usare la ricorsione quando il problema si ripete
La ricorsione si verifica quando una funzione chiama se stessa con una parte più piccola del problema.
AddWeek nell'esempio aggiunge una settimana, quindi si richiama con il primo capitolo per la settimana successiva.
Ogni funzione ricorsiva richiede una condizione che arresta le chiamate.
AddWeek si arresta quando firstChapter supera chapterCount:
if (firstChapter > chapterCount)
{
return;
}
Le funzioni locali funzionano bene per la ricorsione perché i relativi nomi sono visibili nell'ambito dell'intero membro contenitore. Preferisci un ciclo quando esprime il lavoro ripetuto più direttamente. Scegliere la ricorsione quando la struttura ricorsiva semplifica la comprensione dell'algoritmo.
Scegliere una funzione locale o un'espressione lambda
Le funzioni locali e le espressioni lambda possono usare entrambe le variabili circostanti, ma comunicano finalità diverse:
| Scegli | When |
|---|---|
| Funzione locale | L'helper trae vantaggio da un nome, contiene più istruzioni, richiede ricorsione o viene chiamato da più posizioni nel membro contenitore. |
| Espressione lambda | Si passa un comportamento breve direttamente a un altro metodo o lo si archivia in una variabile delegate. |
Il codice seguente usa entrambe le forme:
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 fornisce la regola passata a Where un nome descrittivo. L'espressione lambda passata a Select esegue una breve trasformazione al momento dell'uso. Entrambe le forme forniscono il comportamento a un altro metodo qui. Una funzione locale può anche essere un helper che si invoca direttamente, come AddWeek nell'esempio di piano di lettura.
Usare un metodo regolare anziché una funzione locale quando diversi membri necessitano dell'helper. Usare invece un'espressione lambda quando il comportamento è breve e lo scopo è chiaro dal metodo di ricezione.
Le funzioni locali possono anche essere funzioni iteratori che contengono yield return. Per questo uso, vedere Iteratori.