A Microsoft lançou .NET 10, a versão com suporte de longo prazo (LTS), que será atualizada até 10 de novembro de 2028. A plataforma obteve melhorias significativas de desempenho em cada componente; desde o runtime e as linguagens de programação até as bibliotecas de sistema e as ferramentas de compilação.
A Microsoft também aconselha os desenvolvedores a migrar para o .NET 10 para acelerar a execução e reduzir o consumo de energia dos aplicativos. Para facilitar a migração, o GitHub Copilot pode ser utilizado, ajudando a adaptar o código existente e a atualizar as dependências.
O lançamento do .NET 10 não trouxe uma revolução, mas sim uma série de melhorias direcionadas e consolidadas. A equipe de desenvolvimento da plataforma claramente definiu um rumo para o aprimoramento: menos características experimentais, mais desempenho, conveniência e pureza da API. Vamos analisar os pontos principais neste artigo.
A nova versão de linguagem torna a sintaxe mais flexível sem perda de legibilidade.
Configurações com o field. Agora você pode escrever métodos get/set personalizados, acessando o campo de backup por meio da palavra-chave contextual field. Chega de campos manuais.
public string Name { get => field; set => field = value.Trim(); }
A partir de C# 14, o argumento nameof pode ser um tipo genérico não vinculado. Por exemplo, nameof(List<>) é avaliado como List. Em versões anteriores do C#, para retornar o nome List<int>, só era possível utilizar tipos genéricos fechados (como List).
Essa melhoria ajudará a otimizar o código com menos esforço. O C# aprendeu a realizar mais conversões implícitas, tornando o uso do Span mais agradável.
O Span é um tipo que permite gerenciar a memória de forma eficiente. Com ele, criamos uma espécie de “janela” por meio da qual interagimos com a memória. Além disso, o Span impede o acesso fora dos limites dessa “janela” de memória alocada, algo que poderia acontecer com manipulação insegura. Ele realiza uma verificação automática e lança um erro, se o índice ultrapassar os limites.
O C# 14 reconhece a relação e oferece suporte a algumas conversões entre ReadOnlySpan<T>, Span<T> e T[]. Os tipos span podem atuar como receptores de métodos de extensão, combinar-se com outras conversões e auxiliar em situações de inferência de tipos genéricos.
Os parâmetros como ref, in, out agora podem ser indicados até mesmo em lambdas curtas:
var tryParse = (ref int x) => int.TryParse("42", out x);
A nova solução nos dará a possibilidade de focar no desenvolvimento de código, e não em múltiplas descrições de procedimentos padrão. Isso será especialmente relevante para os parâmetros out.
Anteriormente, o C# 13 já permitia o uso de partial para propriedades e indexadores. Na nova versão, o partial pode ser usado para separar construtores e eventos.
O maior benefício da função partial será recebido pelos criadores de bibliotecas e ferramentas para geração de código.
Os eventos parciais serão especialmente úteis para bibliotecas que suportam eventos fracos. Os construtores parciais, por sua vez, serão úteis para plataformas que geram código compatível.
É importante observar que, ao contrário dos métodos, que só podem ser meramente declarados, os construtores parciais e eventos parciais devem ter implementação completa.
Isso é uma função de otimização que amplia as possibilidades de sobrecarga de operadores nas linguagens de programação. Essa função permite sobrecarregar não apenas os operadores unários e binários, mas também os operadores de atribuição composta, como +=, *= e outros. Como a implementação desses operadores tem muito em comum, no texto a seguir o operador += será considerado. No entanto, todas as conclusões tiradas sobre ele serão aplicadas também aos operadores semelhantes.
É importante observar que, ao usar o operador += na linguagem C# 13, o operador + sobrecarregado é chamado primeiro e, em seguida, o resultado é atribuído.
Ao trabalhar com tipos de valor, a sobrecarga do operador + resulta na cópia adicional de ambos os operandos e na criação de uma nova instância como resultado. Embora esse comportamento seja esperado, ele pode gerar custos indiretos desnecessários de cópia e processamento de dados, especialmente ao trabalhar com tipos grandes, como vetores e tensores matemáticos.
Não é mais necessário converter entre DateOnly e DateTime apenas para obter o número de semana. Isso é especialmente relevante para aplicativos de negócios com intensivo processamento de datas.
public static class ISOWeek { public static int GetWeekOfYear(DateOnly date); public static int GetYear(DateOnly date); public static DateOnly ToDateOnly(int year, int week, DayOfWeek dayOfWeek); }
O modo de atualização de arquivos não carrega mais tudo na memória. A descompactação é paralela. Isso é especialmente perceptível ao trabalhar com arquivos ZIP grandes.
A pesquisa de certificados por impressão digital tornou-se mais segura graças a um novo método FindByThumbprint, que permite especificar explicitamente um algoritmo de hash moderno (como SHA-256), abandonando o obsoleto SHA-1.
O processamento de arquivos PEM foi otimizado para trabalhar com representações em bytes UTF-8. O novo método PemEncoding.FindUtf8 elimina a necessidade de converter bytes em strings, o que reduz o consumo de memória e acelera o parsing.
// Antes do .NET 10 byte[] fileContents = File.ReadAllBytes(path); char[] text = Encoding.ASCII.GetString(fileContents); PemFields pemFields = PemEncoding.Find(text); // .NET 10 byte[] fileContents = File.ReadAllBytes(path); PemFields pemFields = PemEncoding.FindUtf8(fileContents);
A principal inovação — o suporte aprimorado a operações assíncronas .API para exibição de formulários e diálogos, que eram experimentais no .NET 9 e exigiam a desativação do aviso do compilador WFO5002, agora são totalmente estáveis e prontas para uso sem qualquer configuração adicional. Os métodos Form.ShowAsync, Form.ShowDialogAsync e TaskDialog.ShowDialogAsync permitem criar uma interface realmente responsiva sem bloqueios, especialmente ao trabalhar com várias janelas.
No .NET 10, os tipos de editor ausentes do .NET Framework relacionados ao UITypeEditor foram portados para a plataforma. Agora, eles estão disponíveis ao trabalhar com o PropertyGrid e a barra de ações do designer. A funcionalidade SnapLines para designers personalizados também foi corrigida.
Em resposta aos requisitos de segurança modernos, foi adicionada uma API para impedir a gravação de tela. A propriedade Form.ScreenCaptureMode permite um controle flexível durante a captura: ocultar o conteúdo, desfocar completamente a janela ou mantê-la como está. Isso é especialmente relevante para aplicativos que lidam com dados sensíveis.
Uma importante melhoria de desempenho foi implementada nos controles CollectionView e CarouselView no iOS e Mac Catalyst. Os manipuladores otimizados, que estavam disponíveis como um recurso opcional no .NET 9, agora estão habilitados por padrão. Isso garante maior desempenho e estabilidade ao exibir listas complexas com modelos personalizados, além de reduzir o consumo de recursos.
Agora utiliza um manipulador otimizado por padrão.
O componente HybridWebView recebe várias melhorias significativas para uma integração mais estreita entre o código web e .NET:
Eventos de ciclo de vida — os eventos WebViewInitializing e WebViewInitialized agora estão disponíveis, permitindo que você personalize uma WebView no nível da plataforma antes e depois da sua criação.
Uma importante novidade é a capacidade de interceptar requisições dentro do BlazorWebView e HybridWebView. Os desenvolvedores podem modificar cabeçalhos, redirecionar o tráfego ou substituir respostas, abrindo amplas oportunidades para armazenamento em cache, segurança e processamento local de dados.
{ if (e.Uri.ToString().Contains("api/secure")) { e.Handled = true; e.SetResponse(200, "OK", "application/json", GetCustomStream()); } };
O streaming de respostas para HttpClient agora está habilitado por padrão em aplicativos Blazor. Isso significa que o método response.Content.ReadAsStreamAsync() retorna um BrowserHttpReadStream em vez de um MemoryStream, o que reduz o consumo de memória, mas requer cuidado ao usar operações síncronas.
Para preservar o comportamento anterior, existem opções para desabilitá-lo:
<WasmEnableStreamingResponse>false</WasmEnableStreamingResponse>
HttpRequestMessage.SetBrowserResponseStreamingEnabled(false)
No .NET 10, o carregamento de recursos do framework foi aprimorado para ambos os modelos de aplicativos Blazor:
OverrideHtmlAssetPlaceholders como true e adicionar o elemento <link rel="preload" id="webassembly" /> ao elemento <head>.
Agora, os desenvolvedores podem não apenas chamar funções, mas também interagir totalmente com objetos e suas propriedades:
Esses recursos estão disponíveis nos modos assíncrono (IJSRuntime) e síncrono (IJSInProcessRuntime), abrindo novos cenários para a integração perfeita de código .NET e JavaScript em aplicativos híbridos e Blazor.
// Um exemplo de criação e trabalho com uma instância de classe JS var classRef = await JSRuntime.InvokeConstructorAsync("jsInterop.TestClass", "Blazor!"); var text = await classRef.GetValueAsync<string>("text"); var textLength = await classRef.InvokeAsync<int>("getTextLength");
O .NET 10 não é uma versão revolucionária, mas é extremamente refinada. A linguagem tornou-se mais expressiva, o WinForms está mais moderno, o MAUI está mais estável e o Blazor está ainda mais próximo de uma experiência nativa do navegador. Definitivamente vale a pena atualizar, mesmo que você não esteja procurando pela versão mais recente: as correções de problemas antigos e as otimizações de memória se pagam.