.NET C# .NET 10 C# 14 Performance Migração

O que mudou no .NET 10 e C# 14: guia completo de novidades e migração

Guia prático das novidades do .NET 10 e C# 14: extension members, GC DATAS, NativeAOT melhorado, System.Text.Json, ASP.NET Core 10, e checklist de migração.

N
Neryx Digital Architects
16 de agosto de 2026
16 min de leitura
290 profissionais leram
Categoria: .NET Público: Times de engenharia e produto Etapa: Aprendizado

O .NET 10 foi lançado junto com o Visual Studio 2026 como uma release LTS (Long-Term Support) — 3 anos de suporte garantido. Isso significa que, diferente do .NET 9 (STS, 18 meses), o .NET 10 é a versão para onde migrar projetos de produção. E o C# 14, que acompanha o .NET 10, traz a feature mais pedida da história da linguagem: extension members.

Este guia cobre o que realmente importa para quem constrói aplicações empresariais: as features que mudam seu código no dia a dia, os ganhos de performance que vêm de graça, e um checklist de migração para fazer o upgrade sem dor.

C# 14: as novidades da linguagem

Extension members — a feature headline

Desde o C# 3 (2007), extension methods são a forma de "adicionar" métodos a tipos existentes. Funcionam, mas têm limitações: não suportam propriedades, operadores, ou membros estáticos. O C# 14 resolve tudo isso com uma nova sintaxe.

Antes (C# 3-13) — apenas extension methods:

public static class StringExtensions
{
    public static bool IsNullOrEmpty(this string? s) => string.IsNullOrEmpty(s);
    
    // ❌ Impossível: extension property
    // ❌ Impossível: static extension member
    // ❌ Impossível: extension operator
}

Agora (C# 14) — extension members completos:

public static class StringExtensions
{
    // Nova sintaxe com bloco extension
    extension(string? s)
    {
        // ✅ Extension property
        public bool IsNullOrEmpty => string.IsNullOrEmpty(s);
        
        // ✅ Extension method (mesma sintaxe nova)
        public string OrDefault(string fallback) => s ?? fallback;
    }
    
    // ✅ Static extension member — estende o TIPO, não a instância
    extension(string)
    {
        public static string Empty => string.Empty;
    }
}

// Uso:
string? nome = null;
var resultado = nome.IsNullOrEmpty;    // true (property!)
var valor = nome.OrDefault("Anônimo"); // "Anônimo"
var vazio = string.Empty;              // via static extension

Por que importa: Extension properties eliminam a necessidade de métodos com prefixo Get/Is que semanticamente são propriedades. O código fica mais limpo e idiomático. Static extension members permitem "adicionar" factory methods a tipos que você não controla.

Compatibilidade: A nova sintaxe convive com extension methods tradicionais. Não é breaking change — o código antigo continua compilando. A migração é gradual.

Unbound generic types em nameof

Parece pequeno, mas resolve um incômodo antigo:

// Antes (C# 13): precisa especificar tipo genérico inútil
var name = nameof(List<int>); // "List" — mas por que int?

// Agora (C# 14): tipo genérico aberto
var name = nameof(List<>);           // "List"
var name2 = nameof(Dictionary<,>);   // "Dictionary"

Útil em: logging, error messages, reflection wrappers, e qualquer cenário onde você precisa do nome do tipo sem se comprometer com um type argument.

Parâmetros lambda com modificadores

Agora você pode usar scoped, ref, in, out e ref readonly em parâmetros de lambda sem precisar declarar o tipo explicitamente:

// Antes (C# 13): precisa declarar o tipo para usar ref
Span<int> span = stackalloc int[] { 1, 2, 3 };
span.Sort((ref int a, ref int b) => a.CompareTo(b)); // tipo obrigatório

// Agora (C# 14): modificador sem tipo explícito
span.Sort((ref a, ref b) => a.CompareTo(b)); // inferência funciona

Span<T> em overload resolution

O C# 14 melhora a resolução de sobrecarga para métodos com parâmetros Span<T> e ReadOnlySpan<T>. Na prática, isso significa que APIs span-based (como as do System.MemoryExtensions) são resolvidas corretamente em mais cenários, sem casts manuais.

⚠️ Breaking change potencial: Se seu código tem overloads que diferem apenas em string vs ReadOnlySpan<char>, o compilador pode escolher diferente no .NET 10. Rode os testes após migrar.

field keyword (preview)

Ainda em preview no C# 14, mas muito esperado — o keyword field em properties auto-implementadas:

// Antes: precisa declarar backing field manualmente para validação
private string _name = "";
public string Name
{
    get => _name;
    set => _name = value ?? throw new ArgumentNullException(nameof(value));
}

// Com field keyword (preview):
public string Name
{
    get;
    set => field = value ?? throw new ArgumentNullException(nameof(value));
}

Elimina o boilerplate de backing field quando você só precisa de lógica no setter. Ainda é preview — pode mudar na versão final.

.NET 10 Runtime: performance que vem de graça

DATAS: o novo Garbage Collector

A mudança mais impactante do .NET 10 para aplicações server-side é o DATAS (Dynamic Adaptive Thread Allocation for Server GC). Em resumo: o Server GC agora aloca threads dinamicamente baseado na carga real, em vez de criar uma thread por core fixamente.

Impacto prático:

  • Aplicações em containers (Kubernetes, Docker) usam drasticamente menos memória — o GC não aloca threads/heaps para cores que o container não tem acesso real
  • Workloads com picos de tráfego se beneficiam: mais threads GC quando precisa, menos quando está idle
  • Em benchmarks internos da Microsoft, aplicações ASP.NET Core tiveram redução de 20-40% no uso de memória sem nenhuma mudança de código

⚠️ Preparação: DATAS muda o comportamento de memória da sua aplicação. O consumo base será menor, mas o padrão de alocação é diferente. Se você tem alertas de memória calibrados, ajuste os thresholds após migrar. A Microsoft recomenda rodar com DATAS em staging por 1-2 semanas antes de produção.

// Para desabilitar DATAS (voltar ao comportamento antigo):
// Em runtimeconfig.json ou variável de ambiente
{
  "runtimeOptions": {
    "configProperties": {
      "System.GC.Datas": false
    }
  }
}
// Ou: DOTNET_GCDatas=0

JIT: inlining, devirtualização e stack allocations

O JIT do .NET 10 é significativamente melhor em três áreas:

Inlining mais agressivo: Métodos que antes eram "grandes demais" para inline agora são inlined quando o JIT detecta que o benefício compensa. Interfaces com implementação única são devirtualizadas mais frequentemente.

Devirtualização de arrays: Iteração sobre arrays via interface (IEnumerable<T>, IList<T>) agora é devirtualizada — eliminando o overhead de chamadas virtuais em loops hot.

// Este código agora é tão rápido quanto iterar com for/index:
IReadOnlyList<int> items = GetItems(); // retorna int[]
foreach (var item in items) // JIT devirtualiza para acesso direto ao array
{
    Process(item);
}

Stack allocations expandidas: O JIT agora faz escape analysis mais inteligente e aloca mais structs na stack em vez do heap — reduzindo pressão no GC sem que você precise mudar código.

Resultado prático: Aplicações migradas do .NET 9 para .NET 10 sem nenhuma mudança de código mostram 5-15% de melhoria em throughput em benchmarks TechEmpower-style, apenas pelo upgrade de runtime.

NativeAOT melhorado

O NativeAOT no .NET 10 expande a compatibilidade:

  • Suporte melhorado a reflection-heavy patterns (incluindo EF Core com AOT)
  • Binários menores (trimming mais agressivo)
  • Startup ainda mais rápido — APIs simples iniciam em <10ms vs ~50ms no JIT
  • Diagnósticos melhores quando trimming remove código necessário

.NET 10 Libraries: novas APIs

System.Text.Json: serialização mais robusta

// Novo: DisallowDuplicateProperties — rejeita JSON com chaves duplicadas
var options = new JsonSerializerOptions
{
    AllowDuplicateProperties = JsonDuplicatePropertyHandling.Disallow
};

// Lança JsonException se o JSON tiver {"name": "a", "name": "b"}
var obj = JsonSerializer.Deserialize<MyType>(json, options);

// Novo: StrictJsonSerialization — modo estrito completo
var strict = new JsonSerializerOptions
{
    StrictMode = true // rejeita campos extras, tipos incompatíveis, etc.
};

// Novo: Suporte a PipeReader — deserialização streaming eficiente
await JsonSerializer.DeserializeAsync<Order[]>(pipeReader, options);

Por que importa: DisallowDuplicateProperties resolve um problema real de segurança — APIs que recebem JSON com chaves duplicadas podem ter comportamento imprevisível (qual valor vence?). O modo estrito é ideal para contratos de API onde tolerância zero a payloads malformados é requisito.

Cryptography: novas APIs

  • Suporte nativo a ML-KEM (post-quantum key encapsulation) — preparação para criptografia pós-quântica
  • CryptoRandom APIs melhoradas para geração de números aleatórios criptograficamente seguros
  • Performance de hashing (SHA-256, SHA-512) otimizada com AVX-512 quando disponível

Collections: melhorias incrementais

// Novo: OrderedDictionary<TKey, TValue> finalmente na BCL
var ordered = new OrderedDictionary<string, int>
{
    ["primeiro"] = 1,
    ["segundo"] = 2,
    ["terceiro"] = 3
};

// Acesso por índice E por chave:
var byKey = ordered["segundo"];   // 2
var byIdx = ordered.GetAt(1);    // KeyValuePair("segundo", 2)

ASP.NET Core 10: o que muda para APIs

OpenAPI nativo melhorado

O ASP.NET Core 10 expande o suporte a OpenAPI que foi introduzido no .NET 9 (sem Swashbuckle):

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi(options =>
{
    // Novo: transformers para customização do documento
    options.AddDocumentTransformer((doc, context, ct) =>
    {
        doc.Info.Title = "Billing API";
        doc.Info.Version = "v2";
        return Task.CompletedTask;
    });
    
    // Novo: schema transformers para tipos customizados
    options.AddSchemaTransformer((schema, context, ct) =>
    {
        if (context.JsonTypeInfo.Type == typeof(decimal))
            schema.Format = "currency";
        return Task.CompletedTask;
    });
});

var app = builder.Build();
app.MapOpenApi(); // Gera /openapi/v1.json no build

Authentication melhorada

Novos helpers para configuração de OIDC e JWT:

// Novo: configuração simplificada de token handler + named HTTP client
builder.Services.AddAuthentication()
    .AddJwtBearer(options =>
    {
        options.Authority = "https://auth.exemplo.com";
        options.Audience = "billing-api";
        // Novo: validação de token via introspection endpoint automática
        options.UseTokenIntrospection = true;
    });

// Novo: helper para chamar APIs protegidas com token automático
builder.Services.AddHttpClient("IdentityApi")
    .AddTokenHandler(); // injeta Bearer token automaticamente

Melhorias em Minimal APIs

// Novo: validação nativa integrada (sem FluentValidation para casos simples)
app.MapPost("/orders", ([AsParameters] CreateOrderRequest request) =>
{
    // Validação já executada pelo middleware
    return Results.Created($"/orders/{order.Id}", order);
})
.WithValidation(); // ← novo método de extensão

// Novo: problem details automático para erros de validação
// Retorna RFC 7807 com campo "errors" detalhado

// Novo: melhor suporte a OpenAPI para endpoints com AsParameters
// Documentação gerada automaticamente inclui query params corretos

Visual Studio 2026: a IDE acompanha

O Visual Studio 2026 é a primeira IDE oficialmente "AI-integrated" da Microsoft:

  • GitHub Copilot nativo — não é mais extensão, é parte do produto
  • Agent Mode integrado — resolve problemas multi-arquivo dentro do VS
  • Performance profiler com insights de IA — sugere otimizações baseado no perfil de execução
  • Hot Reload expandido — mais cenários suportados, incluindo mudanças em generics
  • Suporte a C# 14 com refactorings automáticos (converter extension methods antigos para nova sintaxe)

Se você usa Rider (JetBrains), o suporte a .NET 10 e C# 14 está disponível desde a versão 2025.3.

Checklist de migração: .NET 9 → .NET 10

A migração do .NET 9 para o .NET 10 é uma das mais suaves da história do .NET — não há breaking changes significativos na maioria dos projetos. Mesmo assim, siga este checklist:

1. Atualize o SDK

# global.json
{
  "sdk": {
    "version": "10.0.100",
    "rollForward": "latestMinor"
  }
}

2. Atualize o target framework

<!-- .csproj -->
<PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <LangVersion>14</LangVersion> <!-- opcional: padrão para net10.0 -->
</PropertyGroup>

3. Atualize pacotes NuGet

# Atualize todos os pacotes Microsoft.* para versão 10.x
dotnet outdated --upgrade

# Ou manualmente os críticos:
dotnet add package Microsoft.EntityFrameworkCore --version 10.0.0
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer --version 10.0.0

4. Verifique breaking changes

Breaking changes confirmados do .NET 10 que podem afetar seu código:

  • Span overload resolution (C# 14) — se você tem overloads string vs ReadOnlySpan<char>, o compilador pode resolver diferente
  • GC DATAS ativado por padrão — comportamento de memória diferente (geralmente melhor, mas alertas podem disparar)
  • System.Text.Json — Source generators atualizados podem gerar código diferente; recompile
  • ASP.NET Core OpenAPI — namespace mudou de Microsoft.AspNetCore.OpenApi para a versão nativa; se usava Swashbuckle, agora é a hora de remover

5. Rode os testes

# Compile e rode todos os testes
dotnet build --warnaserror
dotnet test --no-build

# Se tem testes de performance, compare resultados pré/pós migração
dotnet run --project tests/Benchmarks -c Release

6. Teste em staging com DATAS

# Monitore memória por 1-2 semanas em staging
# Se problemas: desabilite temporariamente
DOTNET_GCDatas=0 dotnet run

7. Aproveite as novidades gradualmente

Não precisa reescrever o código existente. Adote C# 14 em código novo:

// Em novos arquivos, use extension members quando fizer sentido
// Converta extension methods existentes quando tocar no arquivo (Boy Scout Rule)
// Ative analyzers para C# 14 suggestions:
<PropertyGroup>
    <AnalysisLevel>10-recommended</AnalysisLevel>
</PropertyGroup>

Performance: números reais

Baseado nos benchmarks oficiais da Microsoft e de terceiros:

Métrica.NET 9.NET 10Ganho
TechEmpower JSON (req/s)~7.1M~8.2M+15%
Startup time (Minimal API)~48ms~41ms-15%
Startup time (NativeAOT)~12ms~8ms-33%
Memory (container 256MB, idle)~85MB~52MB-39%
GC pause P99 (server)~8ms~5ms-37%
JSON serialization (1KB payload)~1.2μs~0.95μs-21%

O destaque é memória em containers: a combinação DATAS + melhor stack allocation + trimming otimizado faz o .NET 10 usar 30-40% menos memória que o .NET 9 em workloads típicos de API. Para times que pagam por memória (Kubernetes, AWS Fargate, Azure Container Apps), isso se traduz em redução direta de custo de infraestrutura.

Quando migrar: recomendação prática

Migre agora se:

  • Está no .NET 8 LTS — o .NET 10 é o próximo LTS, saltar de 8 para 10 é o caminho natural
  • Está no .NET 9 STS — suporte acaba em 18 meses, melhor migrar agora que a gap é pequena
  • Roda em containers e quer reduzir custo de memória (DATAS sozinho justifica)
  • Quer usar extension properties no código novo (C# 14)

Espere 1-2 meses se:

  • Depende de pacotes third-party que ainda não lançaram versão .NET 10 compatível
  • Tem integração pesada com EF Core + NativeAOT (combinação ainda tem edges)
  • Está em freeze de produção e não pode absorver risco de breaking changes sutis

Não migre se:

  • Está no .NET 8 LTS e funciona — .NET 8 tem suporte até novembro 2026. Se migração não é prioridade, espere até precisar
  • Usa .NET Framework (4.x) — essa é outra conversa inteiramente

Conclusão: LTS que vale o upgrade

O .NET 10 é provavelmente a melhor release LTS da história da plataforma. O combo de C# 14 (extension members finalmente!), DATAS GC (menos memória de graça), e melhorias de JIT (mais throughput sem mudar código) faz a migração ter ROI positivo mesmo em projetos que não pretendem usar features novas.

A recomendação é direta: se você está em produção com .NET 8 ou 9, comece a planejar a migração. O checklist é curto, os breaking changes são mínimos, e o ganho de performance em containers justifica o esforço de uma sprint dedicada ao upgrade.

Quer transformar esse aprendizado em plano de ação?

Se o tema deste artigo se parece com o momento do seu time, podemos ajudar a decidir o próximo passo com clareza.

Falar com um especialista

Newsletter

Receba artigos como este no seu e-mail

Conteúdo técnico sobre arquitetura de software, .NET, IA e gestão de produto. Sem spam.