Visão geral o .NET 10: Novidades no C# 14, ASP.NET Core, WinForms e MAUI
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.
C# 14: o código ficou mais limpo
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(); }
Tipos genéricos não vinculados e nameof
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).
Conversões implícitas no Span<T>
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.
Lambdas com ref/out sem especificar tipos
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.
Construtores parciais e eventos
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.
Sobrecarga de operadores de atribuição composta
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.
Tipos básicos: coisinhas legais
ISOWeek recebeu novas sobrecargas para trabalhar com o tipo DateOnly
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); }
ZipArchive: menos memória, atualizações mais rápidas
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.
Criptografia e certificados: sem legacy
Pesquisa segura de certificados com suporte a algoritmos modernos
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.
Trabalho eficiente com arquivos PEM por meio de UTF-8
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);
Windows Forms: async e proteção de tela
Trabalho assíncrono com formulários
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.
Melhorias do designer
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.
Proteção contra gravação de tela
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.
- Allow — por padrão.
- HideContent — a janela fica preta quando capturada.
- HideWindow — desfoca a janela (requer o Windows 10 20H1 ou posterior).
.NET MAUI: estabilidade e desempenho
Otimização de CollectionView e CarouselView sob o capô
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.
Novas possibilidades no HybridWebView
O componente HybridWebView recebe várias melhorias significativas para uma integração mais estreita entre o código web e .NET:
- Invocação simplificada de JavaScript — adicionada sobrecarga de InvokeJavaScriptAsync para invocar métodos que não retornam um valor.
- Tratamento de exceções — todos os erros do JavaScript agora são automaticamente lançados para o .NET como exceções.
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.
Interceptação de requisições web
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()); } };
ASP.NET Core: Blazor atinge a maturidade
O streaming de respostas no HttpClient agora é o comportamento padrão
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:
- Globalmente via MSBuild:
<WasmEnableStreamingResponse>false</WasmEnableStreamingResponse> - Por requisição
HttpRequestMessage.SetBrowserResponseStreamingEnabled(false)
Pré-carregamento de recursos estáticos do Blazor
No .NET 10, o carregamento de recursos do framework foi aprimorado para ambos os modelos de aplicativos Blazor:
- Para aplicativos Blazor Web, os recursos da plataforma são carregados automaticamente usando cabeçalhos Link, permitindo que o navegador inicie o pré-carregamento mesmo antes que a página inicial seja recebida e renderizada.
- Para aplicativos Blazor WebAssembly independentes, um mecanismo para carregamento e armazenamento em cache de recursos de alta prioridade foi implementado no início do processamento do arquivo index.html. Para habilitar isso, basta definir a propriedade MSBuild
OverrideHtmlAssetPlaceholderscomo true e adicionar o elemento<link rel="preload" id="webassembly" />ao elemento <head>.
Interação JavaScript aprimorada
Agora, os desenvolvedores podem não apenas chamar funções, mas também interagir totalmente com objetos e suas propriedades:
- Criar objetos JS usando construtores que recebem um identificador .NET (InvokeConstructorAsync / InvokeConstructor).
- Ler e gravar propriedades de objetos JS usando os novos métodos GetValueAsync / SetValueAsync e suas contrapartes síncronas.
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");
Conclusão
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.
