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 prefixo com valor "Fruta: ".
  • Criar um Action<string> usando lambda que capture prefixo e imprima prefixo + item.
  • Tentar criar um Action<string> usando static lambda que também tente capturar prefixo (deve ser comentado).
  • Executar o Action para 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

  1. Criamos uma lista de strings com três frutas.
  2. Declaramos a variável prefixo que será capturada.
  3. Criamos um Action<string> com uma lambda que concatena prefixo e o item, e imprime. Essa lambda captura prefixo.
  4. Tentamos criar uma static lambda que também tenta usar prefixo. 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.
  5. Iteramos sobre a lista e chamamos imprimir para 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 prefixo apó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 static sem necessidade: se precisar capturar, não use static.

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