.NET 10 Preview 1: O que há de novo na próxima geração do .NET

O .NET 10 Preview 1 foi anunciado pela Microsoft em 25 de fevereiro de 2025 e abriu o ciclo de desenvolvimento da próxima versão LTS da plataforma. A primeira prévia traz otimizações de performance no JIT, novas APIs nas bibliotecas e os primeiros recursos do C# 14.

O objetivo da nova versão é continuar evoluindo o ecossistema .NET, com mais produtividade e melhor suporte a workloads modernos. Além disso, ela melhora a integração com ferramentas nativas de nuvem, como containers.

Neste artigo, exploramos os principais destaques do .NET 10 Preview 1 e como eles podem impactar o desenvolvimento de aplicações.

Performance e otimizações do JIT no .NET 10 Preview 1

A cada nova versão, a Microsoft foca em aprimorar a performance do runtime, e o .NET 10 Preview 1 não é diferente. Nesta prévia, as principais otimizações estão no compilador JIT (Just-In-Time), que gera o código nativo da aplicação.

As notas de lançamento do runtime destacam três frentes. São elas a desvirtualização de métodos de interface em arrays, a alocação de arrays na stack e o suporte ao AVX10.2.

Desvirtualização de interfaces em arrays

Antes, quando você percorria um array através de uma interface como IEnumerable<T>, as chamadas virtuais permaneciam sem otimização. Ou seja, o JIT não conseguia aplicar inlining nesses casos.

No .NET 10 Preview 1, o JIT reconhece esse padrão e elimina as chamadas virtuais. Com isso, um foreach sobre um array convertido para IEnumerable<int> passa a gerar código tão eficiente quanto a iteração direta.

static int Sum(IEnumerable<int> numbers)
{
    var total = 0;

    // O JIT agora consegue desvirtualizar este loop quando a origem é um array
    foreach (var number in numbers)
        total += number;

    return total;
}

int[] values = [1, 2, 3, 4, 5];
Console.WriteLine(Sum(values));

Essa mudança abre caminho para outras otimizações, como inlining e alocação na stack. Portanto, código que trabalha com abstrações fica mais rápido sem nenhuma alteração.

Alocação de arrays de tipos por valor na stack

Outra otimização permite que o JIT aloque na stack pequenos arrays de tamanho fixo de tipos por valor. A condição é que o array não contenha referências gerenciadas e não sobreviva ao método que o criou.

Por exemplo, um int[] numbers = { 1, 2, 3 }; dentro de um método pode deixar de ir para o heap. Dessa forma, o runtime reduz alocações desnecessárias e diminui a pressão sobre o Garbage Collector.

Suporte ao AVX10.2

O .NET 10 Preview 1 também introduz intrinsics para o conjunto de instruções AVX10.2, em processadores x64. As novas APIs ficam na classe System.Runtime.Intrinsics.X86.Avx10v2.

No entanto, o suporte no JIT vem desabilitado por padrão nesta prévia. Isso acontece porque o hardware com AVX10.2 ainda não estava disponível para testes completos.

E o Garbage Collector?

O Garbage Collector (GC) não recebeu um item próprio nas notas oficiais desta prévia. Contudo, ele se beneficia indiretamente das otimizações do JIT.

Afinal, cada array que vai para a stack em vez do heap é um objeto a menos para o GC coletar. Assim, aplicações com muitas alocações curtas tendem a sentir menos pausas.

As mudanças mais profundas no GC chegaram ao longo do ciclo do .NET 10. Se esse tema interessa, o artigo sobre as mudanças no Garbage Collector do .NET 10 detalha o que mudou na versão final.

Novidades nas bibliotecas do .NET 10 Preview 1

As bibliotecas base receberam uma lista extensa de melhorias no .NET 10 Preview 1. A seguir, estão os destaques mais úteis para o dia a dia.

  • Certificados por outros thumbprints: X509Certificate2Collection.FindByThumbprint aceita SHA-256 ou SHA3-256, e não apenas SHA-1.
  • PEM em bytes: PemEncoding.FindUtf8 lê dados PEM direto de bytes, sem converter para caracteres.
  • ISOWeek com DateOnly: novas sobrecargas de ISOWeek.GetWeekOfYear, ISOWeek.GetYear e ISOWeek.ToDateOnly.
  • Normalização com spans: GetNormalizedLength, IsNormalized e TryNormalize trabalham com spans e evitam novas strings.
  • Comparação numérica de strings: a opção CompareOptions.NumericOrdering ordena "2" antes de "10".
  • TimeSpan.FromMilliseconds: nova sobrecarga com um único parâmetro, compatível com expressões LINQ.

Além disso, o OrderedDictionary<TKey, TValue> ganhou sobrecargas de TryAdd e TryGetValue que devolvem o índice do item. Segundo as notas, isso melhorou entre 10% e 20% a performance de atualização de propriedades em operações com JSON.

Comparação numérica de strings

A comparação numérica era um pedido antigo da comunidade. Com ela, você ordena textos que contêm números de forma natural, e não lexicográfica.

using System.Globalization;

var comparer = StringComparer.Create(CultureInfo.CurrentCulture, CompareOptions.NumericOrdering);

string[] versions = ["10", "2", "1", "21"];

foreach (var version in versions.Order(comparer))
    Console.WriteLine(version); // 1, 2, 10, 21

Também vale notar que "2" e "02" passam a ser considerados iguais. Por isso, o mesmo comparador funciona bem em HashSet<string> e em verificações de igualdade.

ZipArchive e serialização JSON

O ZipArchive recebeu ganhos expressivos de performance. Segundo as notas oficiais, o modo de atualização teve uma redução de 99,8% no tempo de execução em operações com arquivos de 2 GB.

Nesse mesmo cenário, o uso de memória caiu 99,9996%, e a leitura de arquivos melhorou cerca de 18% nas métricas medidas. O artigo sobre as otimizações no ZipArchive do .NET 10 explora esses números em detalhes.

Já no System.Text.Json, o atributo JsonSourceGenerationOptionsAttribute passou a aceitar um ReferenceHandler. Assim, contextos gerados por source generator conseguem preservar referências cíclicas em vez de lançar exceções.

C# 14 no .NET 10 Preview 1

O .NET 10 Preview 1 traz os primeiros recursos do C# 14, a versão da linguagem que acompanha o .NET 10. Entre eles, o mais aguardado é a palavra-chave field em propriedades.

Propriedades com a palavra-chave field

Com field, você acessa o campo de apoio gerado pelo compilador dentro dos acessores. Dessa forma, não precisa declarar um campo privado só para adicionar uma validação.

public class Product
{
    // O compilador cria o campo de apoio, acessado com field
    public string Name
    {
        get;
        set => field = value ?? throw new ArgumentNullException(nameof(value));
    }
}

Antes, essa validação exigia transformar a auto-property em uma propriedade completa, com um campo explícito. Portanto, o novo recurso reduz bastante o código repetitivo.

Outros recursos do C# 14 na prévia

Além de field, a prévia trouxe outras novidades na linguagem. Primeiro, o nameof passou a aceitar tipos genéricos sem argumentos, como nameof(List<>).

Em seguida, o C# ganhou conversões implícitas de primeira classe para Span<T> e ReadOnlySpan<T>. Com isso, o código com spans fica mais natural de escrever.

Também ficou possível usar modificadores como ref, in e out em parâmetros de lambdas sem declarar os tipos. Por fim, há um recurso experimental que grava literais de string como UTF-8 em uma seção de dados separada do executável.

SDK e containers no .NET 10 Preview 1

No SDK, a principal novidade do .NET 10 Preview 1 é a poda de referências de pacotes fornecidos pelo framework. O recurso vem habilitado por padrão e remove pacotes que o próprio framework já entrega.

Na prática, isso reduz o trabalho do restore, diminui o arquivo .deps.json e evita falsos positivos no NuGet Audit. Caso precise desativar, use a propriedade RestoreEnablePackagePruning com valor false.

A poda vale para todos os target frameworks do .NET, como net8.0 e net10.0, e para o .NET Standard 2.0 ou superior. Você pode desativá-la no arquivo do projeto ou no Directory.Build.props.

O recurso também traz três novos avisos, chamados NU1509, NU1510 e NU1511. O artigo sobre NuGet package pruning no .NET 10 explica o mais comum deles, o NU1510, em detalhes.

Já nos containers, as imagens de prévia trocaram o Debian pelo Ubuntu 24.04 como sistema padrão. Além disso, as imagens Ubuntu Chiseled agora incluem o manifesto do Chisel, que permite instalar pacotes extras sobre essas imagens enxutas.

ASP.NET Core no .NET 10 Preview 1

O ASP.NET Core também recebeu melhorias significativas, com foco em OpenAPI e Blazor. A mudança mais visível é o suporte à geração de documentos OpenAPI 3.1.

Nesta prévia, a versão 3.1 passou a ser o padrão e trouxe compatibilidade com o JSON Schema 2020-12. Ainda assim, você pode voltar para a 3.0 pela propriedade OpenApiVersion de OpenApiOptions.

Atenção, porque a mudança inclui uma quebra de compatibilidade. A biblioteca OpenAPI.NET subiu para a versão 2.0, e o tipo OpenApiAny deu lugar ao JsonNode.

Além disso, o documento OpenAPI pode ser servido em YAML. Para isso, basta usar uma rota com o sufixo .yaml ou .yml:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();

var app = builder.Build();

// Serve o documento OpenAPI em YAML
app.MapOpenApi("/openapi/{documentName}.yaml");

app.Run();

Outras novidades do ASP.NET Core nesta prévia incluem:

  • Descrição nas respostas: ProducesResponseType aceita um parâmetro Description para documentar cada resposta.
  • Detecção de URL local: o método RedirectHttpResult.IsLocalUrl ajuda a evitar ataques de open redirect.
  • Testes de integração: um source generator cria a declaração public partial class Program automaticamente.
  • QuickGrid: o novo parâmetro RowClass aplica classes CSS às linhas conforme os dados.
  • Script do Blazor: o arquivo passou a ser um static web asset, com compressão e fingerprinting, e caiu de 183 KB para 43 KB, cerca de 76% menor.

Entity Framework Core no .NET 10 Preview 1

O Entity Framework Core também recebeu atualizações que facilitam o desenvolvimento de aplicações orientadas a dados. O destaque é o suporte nativo ao operador LeftJoin no LINQ.

Antes, um left join exigia combinar GroupJoin, SelectMany e DefaultIfEmpty. Agora, a mesma consulta fica bem mais direta:

var query = context.Students
    .LeftJoin(
        context.Departments,
        student => student.DepartmentId,
        department => department.Id,
        (student, department) => new
        {
            student.FirstName,
            student.LastName,
            Department = department.Name ?? "[NONE]"
        });

Outra mudança relevante está no ExecuteUpdateAsync, que passou a aceitar lambdas comuns em vez de exigir expression trees. Com isso, você usa if e outras estruturas de controle dentro da atualização em lote.

await context.Blogs.ExecuteUpdateAsync(setters =>
{
    setters.SetProperty(blog => blog.Views, 8);

    // Atualiza o nome apenas quando necessário
    if (nameChanged)
        setters.SetProperty(blog => blog.Name, "foo");
});

As notas do EF Core também listam melhorias de tradução e otimização de consultas. Por exemplo, a tradução de DateOnly.ToDateTime, a otimização de cláusulas LIMIT consecutivas e nomes de parâmetros SQL mais simples, como city em vez de @__city_0.

Ao todo, o EF Core 10 Preview 1 reuniu 18 melhorias, 14 correções de regressão e 28 outras correções de bugs. Entre elas, estão a tradução de COUNT sobre ICollection<T> e de MIN e MAX sobre consultas com DISTINCT.

Novidades no .NET MAUI

Para quem desenvolve aplicações multiplataforma com .NET MAUI, a Microsoft focou em qualidade e estabilidade nesta prévia. Entre os destaques, estão melhorias no CollectionView para iOS e Mac Catalyst.

No Android, a prévia adicionou suporte ao Android 16 Beta 1 e ao build com o JDK 21. Além disso, o comando dotnet run passou a funcionar em projetos Android.

Por fim, os avisos do trimmer passaram a vir habilitados por padrão em iOS, Mac Catalyst, macOS e tvOS. Assim, problemas de compatibilidade com trimming aparecem mais cedo no desenvolvimento.

Windows Forms e WPF também receberam atualizações. O Windows Forms ganhou novas APIs de área de transferência e marcou alguns métodos antigos como obsoletos, enquanto o WPF se concentrou em melhorias de qualidade.

O que o .NET 10 Preview 1 ainda não trouxe

Como toda primeira prévia, o .NET 10 Preview 1 é apenas o começo do ciclo. Por isso, áreas como inteligência artificial e observabilidade não tiveram anúncios específicos nesta versão.

O mesmo vale para o Garbage Collector, que evoluiu nas prévias seguintes. Portanto, vale acompanhar cada nova versão para ver como o pacote completo do .NET 10 tomou forma.

Também é importante lembrar que prévias não têm suporte para produção. Assim, use o .NET 10 Preview 1 para testes, protótipos e para preparar seus projetos para a migração.

Como testar o .NET 10 Preview 1

Para experimentar a prévia, baixe o SDK do .NET 10 Preview 1 na página oficial de downloads do .NET. Em seguida, crie um projeto apontando para o novo target framework.

<PropertyGroup>
  <TargetFramework>net10.0</TargetFramework>
  <!-- Habilita recursos da linguagem ainda em prévia -->
  <LangVersion>preview</LangVersion>
</PropertyGroup>

O LangVersion com valor preview libera os recursos do C# 14 disponíveis na prévia. Dessa forma, você consegue testar a palavra-chave field e as demais novidades da linguagem.

Conclusão

O .NET 10 Preview 1 marca o início de uma nova fase para a plataforma, com avanços em performance, novas APIs e os primeiros recursos do C# 14. Além disso, ASP.NET Core, EF Core e .NET MAUI receberam melhorias práticas.

Os destaques ficam com a desvirtualização de arrays no JIT, o OpenAPI 3.1 e o LeftJoin no EF Core. Cada um deles resolve uma dor real de quem desenvolve com .NET.

Se você é desenvolvedor .NET, vale a pena testar essa nova versão e se preparar para as inovações que estão por vir. Afinal, o .NET 10 é uma versão LTS, com suporte estendido.

Fique ligado para mais novidades conforme novas prévias forem lançadas. Com isso, você chega à versão final com o terreno preparado.

Se preferir, o vídeo abaixo também apresenta as novidades do .NET 10 Preview 1.

FAQ

Quando o .NET 10 Preview 1 foi lançado?

A Microsoft anunciou o .NET 10 Preview 1 em 25 de fevereiro de 2025. Ele foi a primeira prévia do ciclo do .NET 10.

Posso usar o .NET 10 Preview 1 em produção?

Não é recomendado. Prévias servem para testes e avaliação, e não contam com suporte para produção.

Qual versão do C# acompanha o .NET 10?

O .NET 10 acompanha o C# 14. A prévia já trazia recursos como a palavra-chave field e o nameof com genéricos sem argumentos.

O que mudou no EF Core nesta prévia?

O destaque é o operador LeftJoin no LINQ. Além disso, o ExecuteUpdateAsync passou a aceitar lambdas comuns.

O .NET 10 é uma versão LTS?

Sim. O .NET 10 é uma versão com suporte de longo prazo.