Desafio C#
Static lambda e captura acidental
Enunciado
Crie um programa que demonstre a diferença entre uma lambda comum e uma static lambda. Use uma lista de strings e um Action<string> que imprime cada item com um prefixo capturado. Depois, tente criar uma static lambda que faça o mesmo e observe o erro de compilação. Comente a linha que causa erro e mostre a saída correta.
Requisitos
- Declarar uma lista de strings com pelo menos 3 frutas.
- Definir uma variável
prefixocom valor "Fruta: ". - Criar um
Action<string>usando lambda que captureprefixoe imprimaprefixo + item. - Tentar criar um
Action<string>usandostaticlambda que também tente capturarprefixo(deve ser comentado). - Executar o
Actionpara cada item da lista e exibir a saída.
Código inicial
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var frutas = new List<string> { "Maçã", "Banana", "Laranja" };
string prefixo = "Fruta: ";
// TODO: criar Action com lambda que captura prefixo
// TODO: tentar criar Action com static lambda (comentar a linha que dá erro)
// TODO: executar o Action para cada fruta
}
}
Saída esperada
Fruta: Maçã
Fruta: Banana
Fruta: Laranja
Ver dica
Para a lambda comum: Action<string> imprimir = item => Console.WriteLine(prefixo + item);. Para a static lambda, tente Action<string> imprimirStatic = static item => Console.WriteLine(prefixo + item); e veja o erro CS8820.
Mostrar solução
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// Lista de frutas
var frutas = new List<string> { "Maçã", "Banana", "Laranja" };
// Variável que será capturada pela lambda comum
string prefixo = "Fruta: ";
// Lambda comum que captura a variável prefixo
Action<string> imprimir = item => Console.WriteLine(prefixo + item);
// Tentativa de usar static lambda que captura prefixo (causa erro de compilação)
// Action<string> imprimirStatic = static item => Console.WriteLine(prefixo + item);
// Executa a lambda para cada fruta
foreach (var fruta in frutas)
{
imprimir(fruta);
}
}
}
Passo a passo
- Criamos uma lista de strings com três frutas.
- Declaramos a variável
prefixoque será capturada. - Criamos um
Action<string>com uma lambda que concatenaprefixoe o item, e imprime. Essa lambda capturaprefixo. - Tentamos criar uma
staticlambda que também tenta usarprefixo. Isso gera o erro CS8820: "Uma lambda estática não pode capturar variáveis externas". A linha está comentada para que o programa compile. - Iteramos sobre a lista e chamamos
imprimirpara cada fruta, exibindo a saída esperada.
Por que funciona
A lambda comum captura a variável prefixo do escopo externo, criando uma closure. Assim, quando executada, ela acessa o valor atual de prefixo. Já a static lambda não pode capturar variáveis, pois é compilada como um método estático sem acesso ao ambiente externo. Isso é útil para evitar alocações desnecessárias e efeitos colaterais.
Erros comuns
- Esquecer de comentar a linha da static lambda: o programa não compila. O erro é:
CS8820: Uma lambda estática não pode capturar 'prefixo'. - Modificar
prefixoapós criar a lambda: a lambda comum verá o novo valor, pois captura por referência. Se quiser fixar o valor, copie para uma variável local. - Usar
staticsem necessidade: se precisar capturar, não usestatic.
Outra forma de resolver
Pode-se usar um método local em vez de lambda, mas a lambda é mais concisa. Para evitar captura, poderia passar prefixo como parâmetro para um método estático.
Saída esperada
Fruta: Maçã
Fruta: Banana
Fruta: Laranja