.NET 11 e C# 15: Recursos e Otimizações no EF Core e LINQ

Hoje teremos uma análise das novidades do .NET↳.NET113 conteúdosNovidades do .NET 9 – o tipo genérico OrderedDictionaryDev (Back & Front) · dez 2024Novidades .NET 10: novas formas de uso do .NET CLIDev (Back & Front) · dez 2025Novidades do .NET 5: implementando um proxy reverso com YARP + ASP.NET 5Dev (Back & Front) · nov 2020Ver tudo em Dev (Back & Front) → 11 Preview 5 e C# 15, com exemplos práticos do mundo real para Union Types, Closed Class Hierarchies, Full Outer Join no LINQ e diagnósticos do EF Core.
A Microsoft disponibilizou a algumas semanas atrás o .NET 11 Preview 5 (na verdade já estamos na preview 7). Para evitar a leitura maçante de notas de lançamento genéricas no GitHub, compilei aqui os recursos essenciais do C# 15 e do ecossistema .NET com explicações e exemplos voltados para o dia a dia do desenvolvimento.
Por se tratar de uma versão de pré-visualização (Preview), estes recursos não devem ser aplicados em ambientes de produção até o lançamento oficial previsto para novembro. No entanto, é fundamental compreender como essas mudanças impactam a modelagem do seu código.
1. C# 15: Tipos Union (Discriminated Unions)
Uma das adições mais solicitadas pelos desenvolvedores C# é o suporte nativo a declarações de union. Inspirado em linguagens como F# e TypeScript, o recurso permite definir um tipo que pode assumir estritamente um conjunto delimitado de outros tipos.
Diferente de abordagens baseadas em herança comum ou interfaces genéricas, o compilador possui conhecimento exato de todos os tipos possíveis da união, tornando a expressão switch totalmente exaustiva sem a necessidade de uma cláusula default:
public record class Cachorro(string Nome);
public record class Gato(int Vidas);
// Declaração do tipo Union
public union Pet(Cachorro, Gato);
// O compilador valida se todos os tipos da Union foram tratados
static string Descrever(Pet pet) => pet switch
{
Cachorro(string nome) => $"Cachorro: {nome}",
Gato(int vidas) => $"Gato com {vidas} vidas"
};
|
Se você adicionar um novo tipo ao Pet futuramente e não atualizar o switch, o compilador emitirá um aviso de compilação (*warning*), garantindo maior segurança em tempo de desenvolvimento.
2. Closed Class Hierarchies (Hierarquias de Classe Fechadas)
Complementando os tipos *union*, o C# 15 introduz o modificador closed para classes base. Ao marcar uma classe como closed, você restringe a herança direta apenas a tipos declarados dentro do mesmo *assembly*.
Isso é extremamente útil para modelar resultados de domínio fortemente tipados (como retornos de APIs ou processamento de negócios), garantindo que nenhuma biblioteca externa possa derivar novas subclasses não mapeadas:
// Classe base fechada para herança fora deste assembly
public closed record class ResultadoPagamento;
// Subclasses explicitamente permitidas dentro do projeto
public record class Sucesso(string TransacaoId) : ResultadoPagamento;
public record class Falha(string Motivo) : ResultadoPagamento;
public record class Pendente(DateTime Previsao) : ResultadoPagamento;
// Garantia de verificação exaustiva sem necessidade de default
static string Processar(ResultadoPagamento resultado) => resultado switch
{
Sucesso(var id) => $"Aprovado! Transação: {id}",
Falha(var motivo) => $"Recusado: {motivo}",
Pendente(var data) => $"Aguardando até {data:dd/MM/yyyy}"
};
|
A grande vantagem frente ao padrão tradicional com abstract e sealed é que o próprio compilador consegue provar que a hierarquia está selada, impondo rigor nos comandos switch.
3. LINQ: Suporte Nativo a Full Outer Joins
Enquanto o SQL↳SQL64 conteúdosSQL Server – Como evitar SQL Injection?Data · mai 2019Azure SQL DB Managed InstanceData · abr 2019SQL Server – Como evitar SQL Injection? Pare de utilizar Query Dinâmica como EXEC(@Query)Data · abr 2019Ver tudo em Data → suporta o comando FULL OUTER JOIN há décadas, as consultas LINQ em memória exigiam combinatórias complexas com GroupJoin e SelectMany. O .NET 11 simplifica isso introduzindo o método FullJoin diretamente no LINQ:
Produto[] catalogo =
[
new("A100", "Teclado"),
new("B200", "Mouse"),
];
Venda[] vendas =
[
new("B200", 4),
new("C300", 2),
];
IEnumerable<object> linhas = catalogo.FullJoin(
vendas,
produto => produto.Sku,
venda => venda.Sku,
(produto, venda) => new
{
Sku = produto?.Sku ?? venda!.Sku,
Nome = produto?.Nome ?? "(fora do catálogo)",
Vendidos = venda?.Quantidade ?? 0,
});
|
O resultado incluirá dados que coincidem em ambos os lados (Mouse B200), dados sem correspondência no lado esquerdo (Teclado A100) e vendas de itens não cadastrados no catálogo (C300). No EF Core, esse método também se estende à interface IQueryable, traduzindo a consulta diretamente para o banco de dados.
4. EF Core: Análise de Chamadas Síncronas (EF1004) e SQL Otimizado
No Entity Framework Core, o Preview 5 traz duas importantes melhorias operacionais:
– Alerta EF1004: O compilador passa a emitir um aviso ao identificar chamadas síncronas em métodos assíncronos (como o uso de .Result ou .GetAwaiter().GetResult() em consultas do EF). Essa prática é uma das maiores causadoras de *starvation* de threads e *deadlocks* sob carga em aplicações ASP.NET Core.
– Geração de SQL mais limpo: A engine de tradução foi ajustada para remover subconsultas redundantes e junções (*joins*) desnecessárias, gerando um código SQL mais próximo do escrito manualmente.
5. Serialização de JSON Lines (NDJSON) e APIs Genéricas de Random
O formato JSON Lines (onde cada linha representa um objeto JSON independente) é amplamente adotado em *pipeline* de dados e *streams* de logs. O namespace System.Text.Json agora suporta essa formatação nativamente via parâmetro topLevelValues: true:
await JsonSerializer.SerializeAsyncEnumerable(
stream,
ObterLeituras(),
topLevelValues: true);
|
Na classe Random.Shared, foram adicionadas sobrecargas genéricas como NextInteger<T>() e NextBinaryFloat<T>(), eliminando a necessidade de converter ou checar tipos manualmente ao escrever algoritmos genéricos.
6. Atualizações no SDK e Blazor
– MCP↳MCP7 conteúdosArquitetura de Sistemas Cognitivos: Integração de RAG, MCP e LLMs no Ecossistema .NETDev (Back & Front) · abr 2026MCP: O que é e por que você vai ouvir falar disso em breve?AI · jul 2025Agentes de IA com LLMs de Código Aberto: Integração Prática com o Model Context Protocol (MCP)AI · ago 2025Ver tudo em AI → Server Template: O CLI do .NET traz o modelo `dotnet new mcp` para facilitar a criação de servidores baseados no *Model Context Protocol*, facilitando a integração de aplicações .NET com agentes de Inteligência Artificial.
– Auditoria de Vulnerabilidades no Build: O processo de compilação passa a alertar automaticamente se algum pacote NuGet do projeto possui CVEs conhecidas ou atingiu o fim de suporte (*EOL*).
– Blazor SSR: Suporte a validação no lado do cliente sem exigir modos interativos completos, compatibilidade do componente `QuickGrid` em páginas estáticas e o atributo [SupplyParameterFromSession] para vincular dados da sessão aos componentes.
Conclusão:
As atualizações do .NET 11 e C# 15 demonstram uma clara evolução voltada para a robustez na modelagem de código e redução de falhas em tempo de execução. Vale a pena criar projetos de teste para explorar os recursos de *Union Types* e *Closed Hierarchies*, pois eles alterarão positivamente a forma como estruturamos o domínio de nossas aplicações.











