Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Escolha uma função local quando quiser dar à lógica auxiliar um nome descritivo e apenas um membro precisa desse auxiliar. Em comparação com um método no tipo contêiner, uma função local informa aos leitores que o auxiliar pertence a essa operação. Seu nome permite que os leitores sigam o fluxo principal antes de inspecionar os detalhes.
Dica
Este artigo ensina o uso prático de funções locais para desenvolvedores que sabem como escrever métodos. Para obter detalhes da declaração e regras de diagnóstico, consulte declarações de função local.
Uma função local é uma função nomeada declarada dentro de outro membro, como um método ou construtor. Seu nome está no escopo somente dentro desse membro.
A seguinte forma declara e chama uma função local:
string CreateMessage(string name)
{
return AddGreeting(name);
string AddGreeting(string value) => $"Hello, {value}!";
}
AddGreeting fica dentro de CreateMessage. Outros membros do tipo não podem chamá-lo.
Manter a lógica auxiliar perto de seu chamador
As funções locais permitem que o fluxo principal declare o que acontece enquanto as funções auxiliares explicam etapas individuais. O exemplo a seguir cria um plano de leitura. Ele usa uma função local para adicionar uma semana de atribuições por vez.
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);
}
}
Um ReadingWeek registra um número da semana e o intervalo de capítulos atribuídos para essa semana.
AddWeek pertence apenas a CreateReadingPlan, de modo que seu escopo local comunica essa relação.
Você pode declarar uma função local antes ou depois das instruções que a chamam. Coloque-o onde os leitores podem seguir o fluxo principal sem perder o contexto.
Usar parâmetros ou capturar o estado local
Uma função local não estática pode usar parâmetros e variáveis locais do membro que a contém. Esse uso é chamado de captura. No exemplo de plano de leitura, AddWeek captura:
-
bookTitle,chapterCountechaptersPerWeekdos parâmetrosCreateReadingPlan. -
plande uma variável local.
A captura é útil quando o helper naturalmente pertence à operação ao redor. Mantenha poucos e óbvios os valores capturados. Se o auxiliar puder receber todos os seus dados por meio de parâmetros, considere uma static função local:
static int LastChapter(int firstChapter, int chaptersPerWeek, int chapterCount) =>
Math.Min(firstChapter + chaptersPerWeek - 1, chapterCount);
Uma função local estática não pode capturar variáveis locais, parâmetros ou estado de instância do membro que contém. Seus parâmetros tornam os dados fornecidos explícitos, enquanto a captura permite que um auxiliar use o contexto da operação que o contém.
Usar a recursão quando o problema se repetir
A recursão ocorre quando uma função chama a si mesma com uma parte menor do problema.
AddWeek no exemplo adiciona uma semana e, em seguida, se chama com o primeiro capítulo para a próxima semana.
Cada função recursiva precisa de uma condição que pare as chamadas.
AddWeek para quando firstChapter exceder chapterCount:
if (firstChapter > chapterCount)
{
return;
}
As funções locais funcionam bem para recursão porque seus nomes estão no escopo em todo o membro que contém. Prefira um loop quando ele expressa o trabalho repetido mais diretamente. Escolha a recursão quando a estrutura recursiva torna o algoritmo mais fácil de entender.
Escolher uma função local ou uma expressão lambda
As funções locais e as expressões lambda podem usar variáveis ao redor, mas comunicam uma intenção diferente:
| Escolher | Quando |
|---|---|
| Função local | O auxiliar se beneficia de um nome, tem várias instruções, precisa de recursão ou é chamado de mais de um local no membro que contém. |
| Expressão lambda | Você passa um comportamento curto diretamente para outro método ou o armazena em uma variável do tipo delegado. |
O código a seguir usa ambas as formas:
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á à regra passada para Where um nome descritivo. O lambda passado para Select realiza uma pequena transformação em seu ponto de uso. Ambos os formulários fornecem comportamento para outro método aqui. Uma função local também pode ser um auxiliar que você chama diretamente, como no exemplo do plano de leitura, em que AddWeek é chamado diretamente.
Use um método comum em vez de uma função local quando vários membros precisarem do auxiliar. Em vez disso, use uma lambda quando o comportamento for curto e sua finalidade estiver clara no método receptor.
As funções locais também podem ser funções de iterador que contêm yield return. Para esse uso, consulte Iteradores.