|
Este artigo apresenta as principais novidades anunciadas com o .NET 11 Preview 5 e C# 15, incluindo Union Types, Full Outer Joins no LINQ, avisos de assincronismo no EF Core e melhorias no Blazor e JSON Lines. |

public record class Cachorro(string Nome); public record class Gato(int Vidas); public union Pet(Cachorro, Gato); static string Descrever(Pet pet) => pet switch { Cachorro(string nome) => $"aachorro: {nome}", Gato(int vidas) => $"gato: {vidas}" }; |
Pet é estritamente um
Cachorro ou um Gato.
O compilador sabe exatamente qual tipo está sendo manipulado, e a expressão
switch torna-se
exaustiva — nenhum caso
default é necessário. Se você esquecer
de tratar uma das opções, o compilador emitirá um aviso.
closed, o compilador restringe a herança
direta apenas ao mesmo assembly:
/// Declara a classe base como closed (fechada) public closed record class ResultadoPagamento; // Subclasses derivadas que representam TODOS os cenários possíveis public record class Sucesso(string TransacaoId) : ResultadoPagamento; public record class Falha(string Motivo) : ResultadoPagamento; public record class Pendente(DateTime Previsao) : ResultadoPagamento; // Como a classe pai é 'closed', o compilador SABE que só existem esses 3 casos. // Se você esquecer de tratar um deles, o código nem compila! static string Processar(ResultadoPagamento resultado) => resultado switch { Sucesso(var id) => $"Pagamento aprovado! ID: {id}", Falha(var motivo) => $"Erro no pagamento: {motivo}", Pendente(var data) => $"Aguardando processamento até {data:dd/MM/yyyy}" }; |
switch
exaustivos e sem brechas para tipos não mapeados. A diferença em relação ao
padrão
abstract
+
sealed é que
agora o próprio compilador consegue provar e impor o fechamento da hierarquia.FULL OUTER JOIN
há décadas, mas as consultas LINQ em memória não possuíam um método direto para
isso até agora.
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?.Name ?? "(fora do catálogo)", Vendidos = venda?.Quantity ?? 0, }); Pendente(var data) => $"Aguardando processamento até {data:dd/MM/yyyy}" }; |
FullJoin
retorna tanto os registros correspondentes quanto os não correspondentes de
ambos os lados. Além do uso em memória, no EF Core esse método está disponível
via
Queryable, traduzindo o
join diretamente no banco de dados.
.Result ou
.GetAwaiter().GetResult()),
prevenindo deadlocks sob carga pesada em produção.topLevelValues: true:
await JsonSerializer.SerializeAsyncEnumerable( stream, GetReadings(), topLevelValues: true); |
Random ganhou métodos
genéricos como
NextInteger<T>()
e
NextBinaryFloat<T>(),
facilitando a geração de números aleatórios em algoritmos genéricos sem a
necessidade de castings ou checagens de tipo.dotnet new para
criar servidores baseados no Model Context Protocol para integração com IA.QuickGrid com SSR estático e o novo atributo
SupplyParameterFromSession.E estamos
conversados..![]()
"Para que possais andar dignamente diante do Senhor, agradando-lhe em tudo,
frutificando em toda a boa obra, e crescendo no conhecimento de Deus;"
Colossenses 1:10
Referências: