NOTíCIAS DO SETOR

.NET 11 Preview 3: Uma análise do desenvolvedor

.NET 11 atinge sua terceira visualização cerca de seis meses antes do planejado GA em novembro de 2026, e ao contrário do Preview 1 e 2, que eram principalmente infraestrutura, o Preview 3 é onde você pode realmente sentir o formato da versão.

Runtime Async deixa de ser um experimento de 'porta de recurso em visualização', o JIT adquire outro lote de otimizações de "dinheiro fácil", o ASP.NET Core recebe o Zstandard pronto para uso, e os tipos de união do C# 15 - o recurso de linguagem do qual as pessoas falam há quase uma década.

Esta não é uma versão LTS, o .NET 11 é a próxima versão de Suporte a Prazo Standard, com 24 meses de suporte, o que já muda o cálculo de se você deve atualizar. Abaixo está o que realmente vale sua atenção como desenvolvedor, e onde ainda estão os pontos críticos.

Tipos de União do C# 15: o grande

Se você tem escrito bibliotecas OneOf<T1, T2>, criando hierarquias de registros selados manualmente, ou apenas invejando desenvolvedores F#, este é o destaque. C# 15 introduz uma palavra-chave de união que declara que um valor é exatamente um de um conjunto fixo de tipos, com exaustividade imposta pelo compilador. Os tipos de união chegaram no Preview 2; O Preview 3 aprimora o suporte IDE em torno deles.

A abordagem da equipe do C# é mais próxima de um tipo união do que das uniões discriminadas do F#: os tipos de membro são tipos existentes que você definiu separadamente, não casos de etiquetas aninhados na declaração de união. Uma união é essencialmente uma struct que envolve um objeto e limita o que pode ser colocado nele. No ponto de chamada, parece nativo - conversão implícita de tipos membros para a união, expressões switch exaustivas sobre Pet.Value, e nenhum braço padrão é necessário quando o compilador consegue ver todos os casos.

[Union]
public partial struct Pet : IUnion
{
    public Pet(Dog dog);
    public Pet(Cat cat);
    public Pet(Bird bird);
}

string Describe(Pet pet) => pet.Value switch
{
    Dog d  => $"Dog named {d.Name}",
    Cat c  => $"Cat ({c.Color})",
    Bird b => $"Bird, {b.Species}",
    // no default - compiler knows the set is closed
};
[Union]
public partial struct Pet : IUnion
{
    public Pet(Dog dog);
    public Pet(Cat cat);
    public Pet(Bird bird);
}

string Describe(Pet pet) => pet.Value switch
{
    Dog d  => $"Dog named {d.Name}",
    Cat c  => $"Cat ({c.Color})",
    Bird b => $"Bird, {b.Species}",
    // no default - compiler knows the set is closed
};
<Union>
Public Partial Structure Pet
    Implements IUnion

    Public Sub New(dog As Dog)
    End Sub

    Public Sub New(cat As Cat)
    End Sub

    Public Sub New(bird As Bird)
    End Sub
End Structure

Function Describe(pet As Pet) As String
    Return pet.Value Select Case
        Case d As Dog
            Return $"Dog named {d.Name}"
        Case c As Cat
            Return $"Cat ({c.Color})"
        Case b As Bird
            Return $"Bird, {b.Species}"
        ' no default - compiler knows the set is closed
    End Select
End Function
$vbLabelText   $csharpLabel

Os benefícios são reais: tipos fechados, nenhum estado inválido, exaustividade em tempo de compilação em vez de às 3 da manhã NotImplementedExceptionat. Adicione um Tubarão à união e cada mudança sobre Pet acende com avisos até que você o trate.

Os contras também são reais e valem a pena serem assinalados em qualquer resenha honesta. A propriedade de Valor exposta do objeto é um mau cheiro - há uma discussão aberta no GitHub sobre escondê-la por trás de algo mais seguro em termos de tipo. Construtores públicos definem implicitamente quais tipos a união aceita, o que não é descobrível nem explícito. A interoperabilidade com o F# não está resolvida (os dois modelos são fundamentalmente diferentes). E a história mais ampla de exaustividade ainda tem lacunas: hierarquias fechadas e enums fechados, as duas propostas que completariam o quadro, ainda são propostas. Unions sozinhos são ótimos. Unions mais enums fechadas, mais hierarquias fechadas seriam uma mudança geracional. Ainda não chegamos lá.

Runtime Async V2 e melhorias no JIT

Runtime Async é a reescrita silenciosa do .NET de como async/await realmente executa. Em vez de o compilador C# emitir uma classe de máquina de estado por método assíncrono, o próprio tempo de execução gerencia suspensão e retomada. O retorno visível: rastreamentos de pilha mais limpos, alocações menores e um depurador que não faz você rolar além de quadros MoveNext para encontrar seu próprio código.

No Preview 3, o Runtime Async elimina o requisito EnablePreviewFeatures. Você ainda ativa o recurso - <Features>runtime-async=on</Features> - mas não precisa mais optar por todas as chamadas de API no território de pré-visualização. O suporte a NativeAOT e ReadyToRun também chegou nesta visualização, o que fecha a lacuna entre os cenários de JIT e AOT. Objetos de continuação são reutilizados de forma mais agressiva, e locais que não mudaram não são salvos entre suspensões. Em caminhos de código pesados em async - pense em um pipeline Kestrel ou em um trabalhador de consulta do EF Core - isso é uma queda significativa na pressão de alocação.

O JIT pegou seu lote habitual de "seu código existente agora é mais rápido, não faça nada":

  • Expressões switch multi-alvo como x é 0 ou 1 ou 2 ou 3 ou 4 agora se dobram em verificações sem ramificação.
  • Verificações de limites em padrões de valores[^1] + valores[^2] são eliminadas de forma mais agressiva, e o caso comum i + cns < len em loops cai limpo.
  • Casts de inteiro sem sinal para float e inteiro sem sinal para double são mais rápidos em hardware x86 pré-AVX-512 - nicho, mas real se você estiver em máquinas mais antigas.

Usuários WebAssembly recebem carregamento de payload WebCIL diretamente no runtime, melhores símbolos de depuração, e marshaling float[] / Span<float> / ArraySegment<float> sem o overhead da ida e volta. Nenhum destes é individualmente dramático, mas juntos, eles são o tipo de trabalho que compõe que faz com que Blazor WASM pareça menos como um compromisso.

O problema é o piso de hardware. .NET 11 eleva os requisitos mínimos de conjunto de instruções em x86/x64 e Arm64. Apple Silicon e a maioria dos SBCs Linux estão bem - o alvo ReadyToRun no Arm64 apenas adiciona LSE - mas hardware x86 muito antigo está fora. Audite sua frota antes de presumir uma atualização no local.

ASP.NET Core e Blazor

Zstandard é o destaque aqui. O ASP.NET Core agora suporta zstd tanto para compressão de resposta quanto para descompressão de solicitação, e ele é habilitado por padrão quando você adiciona o middleware. A configuração tem o mesmo formato que você esperaria:

builder.Services.AddResponseCompression();
builder.Services.AddRequestDecompression();
builder.Services.Configure<ZstandardCompressionProviderOptions>(options =>
{
    options.CompressionOptions = new ZstandardCompressionOptions { Quality = 6 };
});
builder.Services.AddResponseCompression();
builder.Services.AddRequestDecompression();
builder.Services.Configure<ZstandardCompressionProviderOptions>(options =>
{
    options.CompressionOptions = new ZstandardCompressionOptions { Quality = 6 };
});
Imports Microsoft.Extensions.DependencyInjection

builder.Services.AddResponseCompression()
builder.Services.AddRequestDecompression()
builder.Services.Configure(Of ZstandardCompressionProviderOptions)(Sub(options)
    options.CompressionOptions = New ZstandardCompressionOptions With {.Quality = 6}
End Sub)
$vbLabelText   $csharpLabel

Para APIs que servem cargas úteis JSON ou de texto para clientes que já falam zstd - cada vez mais comum em ecossistemas móveis e adjacentes ao gRPC - isso é uma vitória mensurável de largura de banda sem ter que depender de uma biblioteca de terceiros. Também é, notavelmente, uma contribuição da comunidade em vez de uma interna da Microsoft, o que é um sinal saudável.

O Virtualize<TItem> do Blazor finalmente para de assumir que todas as linhas têm a mesma altura. Isso foi uma irritação de longa data: qualquer lista com conteúdo variável - comentários, mensagens de chat, qualquer coisa com texto envolto - precisava de soluções manuais. Agora o componente mede os itens em tempo de execução. A versão Preview 3 também corrige um conjunto de bugs do Blazor: uma referência nula em Virtualize, detecção de contêiner de rolagem com overflow-x, o modelo Web Worker em aplicativos WASM publicados, casos extremos de carregamento preguiçoso TempData, e um vazamento de IJSObjectReference em ResourceCollectionProvider. Individualmente pequenos, coletivamente o tipo de limpeza que sinaliza que o framework está amadurecendo além da fase de 'algo novo a cada lançamento'.

Kestrel também começa a processar solicitações HTTP/3 sem esperar pelo fluxo de controle e pelo quadro SETTINGS, o que reduz a latência da primeira solicitação em novas conexões. Se você tem medido P99s de HTTP/3 e visto caudas de inicialização fria estranhas, esta é sua solução.

.NET MAUI

MAUI no Preview 3 é principalmente sobre fechar lacunas que fazem parecer um beta durante muito tempo. O controle Map recebe agrupamento de pinos, ícones de pinos personalizados, estilo JSON personalizado, e eventos de clique em círculos, polígonos e polilinhas - tudo que as interfaces de mapa de produção realmente precisam e que anteriormente exigiam manipuladores customizados por plataforma. Um LongPressGestureRecognizer embutido agora está disponível sem precisar criar o seu próprio. Declarações implícitas de namespace XAML estão ativas por padrão, o que reduz o boilerplate no topo de cada arquivo.

A paridade de plataforma recebe um aumento: Permissions.PostNotifications agora está implementado no iOS (antes era exclusivo para Android), e o Android recebe suporte de pré-visualização para Android 17 e nível de API 37.

A avaliação honesta: esta é uma iteração contínua e sensata, não uma reinvenção. MAUI em 2026 está em um lugar muito melhor do que MAUI em 2023, mas se você se afastou dele antes em sua vida, o Preview 3 sozinho não vai trazê-lo de volta. Se você já está no MAUI, essas são exatamente as mudanças de QoL que você deseja.

SDK, CLI e .NET watch

Esta é a seção onde as pequenas coisas se acumulam. Algumas que eu acho que genuinamente mudam o fluxo de trabalho diário:

.NET sln agora pode criar e editar filtros de solução (.slnf) diretamente do CLI. Para monorepos e grandes soluções no estilo Microsoft, abrir uma SLN de 200 projetos para trabalhar em três deles tem sido um custo real. Agora você pode delimitar a partir do terminal:

dotnet new slnf --name MyApp.slnf
dotnet sln MyApp.slnf add src/Lib/Lib.csproj
dotnet new slnf --name MyApp.slnf
dotnet sln MyApp.slnf add src/Lib/Lib.csproj
SHELL

Aplicativos baseados em arquivo (o fluxo de trabalho de .NET run app.cs) finalmente suportam #:include, o que significa que scripts C# podem dividir auxiliares em arquivos separados. Combinado com a conclusão do editor para a diretiva no Roslyn, isso empurra aplicativos baseados em arquivo de "brinquedo" para "viável para ferramentas de automação reais" - o nicho que PowerShell e pequenos scripts Python têm possuído por anos.

.NET run -e FOO=BAR permite que você passe variáveis de ambiente na linha de comando sem exportar o estado do shell ou editar perfis de inicialização. Pequeno, mas se você já teve três terminais abertos com diferentes valores ASPNETCORE_ENVIRONMENT, você conhece a dor.

.NET watch integra-se com hosts de aplicativos Aspire, relança automaticamente após um crash na próxima alteração de arquivo, e lida com o Ctrl+C de forma mais graciosa para WinForms e WPF (um corte de papel perpétuo). .NET format aceita --framework para projetos multi-alvo. .NET test no modo MTP suporta --artifacts-path. E .NET tool exec / dnx não solicita mais uma aprovação extra, que era um ponto de atrito para execuções de ferramenta pontuais.

Os pontos de dor

Uma revisão equilibrada deve reconhecer as arestas, e o Preview 3 as tem.

A história das ferramentas é complicada. O Visual Studio 2026 ainda está em visualização seis meses após o lançamento do .NET 10, e os agentes de construção hospedados pela Microsoft ainda não têm suporte estável para o VS 2026. Uma alteração em uma versão de patch do SDK do .NET 10 exigia o MSBuild 18 (VS 2026), o que é uma violação clara das garantias de semver que a Microsoft promove. Qualquer um que esteja executando CI em agentes hospedados pela Microsoft teve que fixar o SDK 10.0.4 ou mudar para imagens de construção em visualização. Se você está considerando mover pipelines de CI para visualizações do .NET 11, espere mais do mesmo - SDKs de visualização, por admissão da própria equipe, quebraram coisas nas 10.0.2 e 10.0.3 antes de estabilizar.

Runtime Async ainda é opt-in. Mesmo com a barreira de recursos de pré-visualização removida, você tem que ativar runtime-async=on. Isso é bom para código greenfield; para bibliotecas enviadas no NuGet, você ainda não pode presumir que seus consumidores ativaram a chave, então os benefícios práticos são adiados até que o recurso esteja ativado por padrão (não no .NET 11).

Aumentos nos requisitos de hardware. Os requisitos mínimos de conjunto de instruções x86/x64 foram aumentados. A maioria das equipes não vai notar. Algumas vão - e elas descobrirão no momento da implantação se não fizerem uma auditoria primeiro.

STS, não LTS. .NET 11 é suportado por 24 meses. .NET 10, o LTS atual, recebe suporte por 36 meses. Para empresas com cadências de atualização lentas, .NET 10 ainda é a escolha mais conservadora, e adotar .NET 11 significa comprometer-se com outra atualização em 2028. O argumento para adotar um STS são os recursos; o argumento contra é o calendário.

Visualização significa visualização. Isso não é uma crítica de estabilidade - o processo de visualização da Microsoft tem sido bom - mas o Preview 3 não é um candidato a lançamento. Implantações de produção esperam pelo RC1 no mínimo. Ferramentas internas, projetos paralelos e exploração são o escopo certo agora.

Veredicto

Se você escreve C# todos os dias, o .NET 11 Preview 3 vale a instalação e experimentação esta semana - particularmente para explorar mãos em tipos de união, que são a mudança de linguagem mais consequente em anos. Se você mantém bibliotecas, o trabalho no JIT e Runtime Async significa que seu código ficará mais rápido no .NET 11 sem edições, que é o melhor tipo de atualização. Se você envia aplicativos MAUI, o trabalho no Mapa e gestos é um progresso real.

Se você executa cargas de trabalho de produção .NET, a resposta é a aborrecida: continue planejando, continue assistindo, e marque o GA em novembro. As partes que entusiasmam estão chegando, mas a cadeia de ferramentas - VS, agentes de construção e a cadência de patch do SDK - é onde realmente vive o atrito, e isso ainda não foi resolvido.

| --- |

Fontes: Anúncio do blog do .NET, Novidades no .NET 11 (Microsoft Learn), Notas de release do Runtime, Notas de release do ASP.NET Core, Notas de release do SDK, Explore tipos de união no C# 15.