A questão mais prática é se esses novos recursos são suficientes para justificar
a saída do .NET 10. Para algumas equipes, especialmente aquelas que constroem
APIs com uso intenso de código assíncrono, aplicativos móveis ou cargas de
trabalho numéricas, pode valer a pena se planejar para o .NET 11.
Para
muitas outras, o .NET 10 continuará sendo a melhor opção para produção por
enquanto. Este artigo analisa o que realmente mudou, onde essas mudanças
importam e se vale a pena ajustar seus planos de migração para elas
Roteiro das atualizações do .NET 11 que veremos neste artigo :
1. Runtime Async:
Como o async/await muda por baixo dos panos.
2. CoreCLR no .NET MAUI: Apps
móveis mudam para a mesma família de runtime dos servidores e desktop.
3.
Zstandard: Compressão moderna integrada em System.IO.Compression.
4.
BFloat16: Um número de 16 bits voltado para IA e cargas de trabalho numéricas.
5. ASP.NET Core & Blazor: Algumas melhorias práticas para web que valem a
pena notar.
6. C# 15 + EF Core 11: Recursos de linguagem e acesso a dados
com os quais a maioria dos desenvolvedores se importará.
Nota:
Recursos em preview ainda podem mudar antes da versão GA.
1. Runtime Async é o
destaque
Você provavelmente já escreveu um
método como este centenas de vezes
:
public async Task<Order?> GetOrderAsync(
int orderId,CancellationToken cancellationToken)
{
return await repository.FindAsync(orderId, cancellationToken);
}
|
Parece simples. Chame algo, aguarde sem bloquear a thread, continue
quando o resultado chegar.
Por trás desse inocente await, no entanto, o
compilador C# tradicionalmente construía uma pequena máquina para lembrar onde o
método parou, quais variáveis ainda precisa e como reiniciá-lo mais tarde.
Tradicionalmente, ele reescreve o método em uma máquina de estados que
lembra onde a execução foi pausada, quais valores ainda são necessários e onde o
método deve continuar uma vez concluída a operação aguardada.
Pense em um
trabalhador deixando um bilhete antes de se afastar de uma tarefa:
- onde o
trabalho parou;
- quais informações ainda são necessárias;
- qual
resultado ele está esperando;
- onde continuar depois.
Esse bilhete
é uma maneira simplificada de entender a máquina de estados assíncrona.
Tecnicamente, o compilador gera uma estrutura contendo o estado atual, um
construtor de método assíncrono (async method builder), awaiters e quaisquer
parâmetros ou variáveis locais que devam sobreviver a uma suspensão. Um método
gerado chamado MoveNext() controla o fluxo de pausa e retomada.
O
CoreCLR pode executar esse IL gerado, mas tradicionalmente não entende o método
assíncrono original como uma operação de primeira classe. Ele vê principalmente
campos gerados, builders, tasks, chamadas de método e continuações.
O
.NET 11 começa a mudar essa relação.
Async Tradicional vs Runtime Async
Afinal o que o Runtime Async muda ?
O Runtime Async dá ao CoreCLR um
papel mais direto na execução assíncrona.
O compilador ainda identifica a
estrutura async, mas o runtime agora pode reconhecer pontos de suspensão,
preservar o estado que realmente é necessário e retomar o método lógico de forma
mais direta.
Seu código C# permanece o mesmo:
public async Task<Customer> LoadCustomerAsync(int id)
{
return await customerClient.GetAsync(id);
} |
|
A mudança acontece por baixo dele. No preview atual, o Runtime
Async permanece opt-in para código de aplicação:
<PropertyGroup> <TargetFramework>net11.0</TargetFramework>
<Features>runtime-async=on</Features> </PropertyGroup> |
Os benefícios potenciais incluem menor overhead em caminhos com uso
intensivo de async, menos alocações em alguns padrões, menor pressão no garbage
collector e stack traces ao vivo mais limpos.
Isso não significa que toda
API se torne dramaticamente mais rápida. Se a maior parte de uma requisição é
gasta esperando por um banco de dados ou um serviço externo, o Runtime Async não
consegue remover essa latência.
Seu impacto tem mais chance de aparecer
em aplicações que realizam um grande número de operações assíncronas pequenas,
como APIs de alto throughput, pipelines de middleware, consumidores de mensagens
e bibliotecas de networking.
A melhoria no debugging pode ser mais fácil
de notar. Em vez de expor stacks cheias de builders, continuações e MoveNext(),
as ferramentas de diagnóstico podem mostrar a cadeia de chamadas async lógica de
forma mais direta:
LoadOrderAsync
LoadCustomerAsync
HandleRequestAsync
Isso pode não produzir o benchmark
mais empolgante, mas pode tornar um problema de produção muito mais fácil de
entender.
2. O CoreCLR finalmente chega ao .NET MAUI
Por anos, o .NET usou implementações de runtime diferentes dependendo de
onde a aplicação roda.
Aplicações server e desktop geralmente usavam o
CoreCLR, enquanto aplicações mobile e Blazor WebAssembly dependiam do Mono. Essa
divisão permitiu que o .NET suportasse ambientes muito diferentes, mas também
significava que melhorias de runtime e ferramentas de diagnóstico nem sempre
chegavam a todos os lugares ao mesmo tempo.
O .NET 11 muda esse cenário
para o .NET MAUI.
O CoreCLR agora é o runtime usado por aplicações MAUI
que miram Android, iOS e Mac Catalyst. Aplicações mobile estão migrando para a
mesma família de runtime já usada por serviços ASP.NET Core e aplicações
desktop.

A principal vantagem é a consistência. Aplicações MAUI podem se beneficiar
do trabalho de runtime do CoreCLR e usar ferramentas de diagnóstico familiares
como dotnet-trace e dotnet-counters em dispositivos reais.
Isso não
significa que toda aplicação MAUI automaticamente ficará mais rápida ou menor.
Tempo de startup, tamanho do pacote, linking, reflection, renderização de UI e
hardware do dispositivo ainda importam. As equipes devem testar suas próprias
aplicações antes de tirar conclusões.
Há também uma exceção importante: o
Blazor WebAssembly ainda usa Mono no .NET 11. A Microsoft está trabalhando em
infraestrutura relacionada ao RyuJIT e CoreCLR para WebAssembly, mas essa
transição ainda não está completa
3.
Zstandard se torna uma opção nativaO .NET
11 adiciona suporte a compressão Zstandard em System.IO.Compression.
O Zstandard, geralmente chamado de Zstd, é um formato de
compressão moderno comumente usado para logs, datasets, caches, backups e
comunicação entre serviços internos. Até agora, equipes .NET tipicamente
precisavam de um pacote de terceiros ou wrapper nativo para usá-lo.
Um exemplo básico fica assim: