Programação Funcional em C#: princípios e exemplos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Programação Funcional em C#: da Teoria à Prática

Programação Funcional (PF) é um paradigma onde os cálculos são tratados como avaliação de funções matemáticas, evitando mudanças de estado e dados mutáveis. Embora C# tenha sido originalmente uma linguagem orientada a objetos, a partir da versão 3.0 ela vem absorvendo ativamente recursos funcionais. Hoje, C# suporta conceitos como expressões lambda, LINQ, tipos imutáveis e até pattern matching. Neste artigo, vamos analisar os princípios-chave da PF e mostrar como aplicá-los em projetos reais com C#.



1. Funções Puras e Ausência de Efeitos Colaterais

Função pura é uma função que:

  • Sempre retorna o mesmo resultado para os mesmos argumentos (transparência referencial).
  • Não possui efeitos colaterais (não altera estado global, não escreve em arquivos, não envia requisições HTTP).

Em C#, uma função pura pode ser assim:

public static int Add(int a, int b) => a + b;

Já um exemplo de função impura:

public static int AddAndLog(int a, int b){    Console.WriteLine($"Somando {a} e {b}"); // efeito colateral    return a + b;}

Vantagens das funções puras: são fáceis de testar, depurar e paralelizar.



2. Imutabilidade (Immutability)

Na PF, os dados são imutáveis por padrão. Em C#, usamos para isso:

  • A palavra-chave readonly para campos.
  • Structs record (C# 9+), que criam automaticamente objetos imutáveis.
  • Coleções do namespace System.Collections.Immutable.

Exemplo com record:

public record Person(string Name, int Age);

Se precisar alterar a idade, uma nova instância é criada:

Person person = new("Ivan", 30);Person olderPerson = person with { Age = 31 };

A imutabilidade previne mutações acidentais e simplifica a concorrência.



3. Funções de Alta Ordem e Expressões Lambda

Funções de alta ordem recebem outras funções como argumentos ou as retornam. Em C#, isso é implementado através de delegates: Func<>, Action<>, Predicate<>.

Um exemplo simples é o método Where do LINQ:

List<int> numbers = new() { 1, 2, 3, 4, 5 };var evenNumbers = numbers.Where(n => n % 2 == 0).ToList();

Aqui, n => n % 2 == 0 é uma expressão lambda (função anônima).

Podemos escrever nossa própria função de alta ordem:

public static List<T> Filter<T>(List<T> list, Func<T, bool> predicate){    var result = new List<T>();    foreach (var item in list)        if (predicate(item)) result.Add(item);    return result;}


4. LINQ: Poderosa Ferramenta de Estilo Funcional

LINQ (Language Integrated Query) é, talvez, o exemplo mais marcante de programação funcional em C#. Ele permite processar coleções de forma declarativa, como em SQL.

Exemplo: obter nomes de usuários maiores de 18 anos, ordenados por idade:

var users = new List<User>{    new("Anna", 22),    new("Boris", 17),    new("Victor", 30)};

var result = users .Where(u => u.Age >= 18) .OrderBy(u => u.Age) .Select(u => u.Name) .ToList();

LINQ suporta execução tardia (lazy evaluation), economizando recursos.



5. Mônadas e Tipo Maybe em C#

Mônadas são uma abstração para encadeamento de computações com contexto (por exemplo, tratamento de null ou assincronia). Em C#, não há uma mônada Maybe embutida, mas é fácil implementá-la:

public class Maybe<T>{    private readonly T _value;    public bool HasValue { get; }        p                

Blogs

Book Recommendations