Partilhar via


O que há de novo no SDK e nas ferramentas do .NET 9

Este artigo descreve os novos recursos no SDK do .NET e ferramentas para .NET 9.

Testes unitários

Esta seção descreve as atualizações para testes unitários no .NET 9: execução de testes em paralelo e saída de testes através do Terminal Logger.

Executar testes em paralelo

No .NET 9, dotnet test é mais totalmente integrado com o MSBuild. Como o MSBuild oferece suporte à criação de em paralelo, você pode executar testes para o mesmo projeto em diferentes estruturas de destino em paralelo. Por padrão, o MSBuild limita o número de processos paralelos ao número de processadores no computador. Você também pode definir seu próprio limite usando o -maxcpucount switch. Se você quiser desativar o paralelismo, defina a propriedade TestTfmsInParallel MSBuild como false.

Visor de teste do Terminal Logger

O relatório de resultados de teste para dotnet test agora é suportado diretamente no MSBuild Terminal Logger. Pode obter relatórios de teste mais completos enquanto os testes estão em execução (exibe o nome do teste em execução) e depois que os testes são concluídos (quaisquer erros de teste são apresentados de uma forma mais eficaz).

Para obter mais informações sobre o Terminal Logger, consulte opções de compilação Dotnet.

Avanço da ferramenta .NET

Ferramentas .NET são aplicações dependentes da framework que pode instalar globalmente ou localmente e, em seguida, executar usando o SDK do .NET e os runtimes do .NET instalados. Essas ferramentas, como todos os aplicativos .NET, destinam-se a uma versão principal específica do .NET. Por padrão, os aplicativos não são executados em versões mais recentes do .NET. Os autores de ferramentas puderam optar por executar suas ferramentas em versões mais recentes do tempo de execução do .NET definindo a propriedade RollForward MSBuild. No entanto, nem todas as ferramentas o fazem.

Uma nova opção para dotnet tool install permite aos usuários decidir como as ferramentas .NET devem ser executadas. Quando você instala uma ferramenta via dotnet tool install, ou quando executa a ferramenta via dotnet tool run <toolname>, você pode especificar um novo sinalizador chamado --allow-roll-forward. Esta opção configura a ferramenta com o modo de avanço contínuo Major. Esse modo permite que a ferramenta seja executada em uma versão principal mais recente do .NET se a versão correspondente do .NET não estiver disponível. Esse recurso ajuda os primeiros usuários a usar ferramentas .NET sem que os autores de ferramentas precisem alterar qualquer código.

Registador Terminal

O Terminal Logger agora está habilitado por padrão e também melhorou a usabilidade.

Ativado por padrão

A partir do .NET 9, a experiência padrão para todos os comandos da CLI do .NET que usam o MSBuild é o Terminal Logger, a experiência de log aprimorada lançada no .NET 8. Esta nova saída usa as capacidades dos terminais modernos para fornecer funcionalidades como:

  • Links clicáveis
  • Temporizadores de duração para tarefas do MSBuild
  • Codificação de cores de mensagens de aviso e erro

A saída é mais condensada e utilizável do que o registrador de console MSBuild existente.

O novo registador tenta detetar automaticamente se pode ser utilizado, mas também pode controlar manualmente se o Terminal Logger é utilizado. Especifique a opção de linha de comando para desabilitar o --tl:off Terminal Logger para um comando específico. Ou, para desativar o Terminal Logger de forma mais ampla, defina a variável de MSBUILDTERMINALLOGGER ambiente como off.

O conjunto de comandos que usa o Terminal Logger por padrão é:

  • build
  • clean
  • msbuild
  • pack
  • publish
  • restore
  • test

Usabilidade

O Terminal Logger agora resume a contagem total de falhas e avisos no final de uma compilação. Também mostra erros que contêm novas linhas. (Para obter mais informações sobre o Terminal Logger, consulte as opções 'dotnet build', especificamente a --tl opção.)

Considere o seguinte arquivo de projeto que emite um aviso quando o projeto é criado:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>

  <Target Name="Error" BeforeTargets="Build">
    <Warning Code="ECLIPSE001" Text="Black Hole Sun, won't you come
  And wash away the rain
    Black Hole Sun, won't you come
      won't you come" />
  </Target>
</Project>

Quando você executa dotnet build -tl no SDK do .NET 8, a saída é como mostrado após este parágrafo. Cada linha do aviso multilinhas aparece como uma linha separada, com um prefixo completo da mensagem de erro na saída, o que dificulta a leitura. Além disso, o resumo final da construção diz que havia avisos, mas não quantos havia. As informações ausentes podem tornar difícil determinar se uma compilação específica é melhor ou pior do que as compilações anteriores.

$ dotnet build -tl
MSBuild version 17.8.5+b5265ef37 for .NET
Restore complete (0.5s)
  multiline-error-example succeeded with warnings (0.2s) → bin\Debug\net8.0\multiline-error-example.dll
    E:\Code\multiline-error-example.csproj(11,5): warning ECLIPSE001: Black Hole Sun, won't you come
E:\Code\multiline-error-example.csproj(11,5): warning ECLIPSE001:   And wash away the rain
E:\Code\multiline-error-example.csproj(11,5): warning ECLIPSE001:     Black Hole Sun, won't you come
E:\Code\multiline-error-example.csproj(11,5): warning ECLIPSE001:       won't you come
Build succeeded with warnings in 0.9s

Quando você cria o mesmo projeto usando o SDK do .NET 9, a saída é a seguinte:

> dotnet build -tl
Restore complete (0.4s)
You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy
  multiline-error-example succeeded with 3 warning(s) (0.2s) → bin\Debug\net8.0\multiline-error-example.dll
    E:\Code\multiline-error-example.csproj(11,5): warning ECLIPSE001:
      Black Hole Sun, won't you come
        And wash away the rain
          Black Hole Sun, won't you come
            won't you come
Build succeeded with 3 warning(s) in 0.8s

As linhas de mensagem do aviso já não incluem as informações repetidas de projeto e localização que desorganizam a apresentação. Além disso, o resumo da compilação mostra quantos avisos (e erros, se houver) foram gerados durante a compilação.

Se você tiver comentários sobre o Terminal Logger, poderá fornecê-los no repositório do MSBuild.

Resolução de dependência NuGet mais rápida para repositórios grandes

O resolvedor de dependência do NuGet foi revisado para melhorar o desempenho e a escalabilidade de todos os <PackageReference> projetos. Ativado por padrão, o novo algoritmo acelera as operações de restauração sem comprometer a funcionalidade, seguindo estritamente as principais regras de resolução de dependência.

Se encontrar algum problema, como falhas de restauração ou versões inesperadas do pacote, pode reverter para o resolvedor anterior.

Analisadores de script MSBuild ("BuildChecks")

O .NET 9 apresenta um recurso que ajuda a proteger contra defeitos e regressões em seus scripts de compilação. Para executar as verificações de compilação, adicione o sinalizador /check a qualquer comando que invoque MSBuild. Por exemplo, dotnet build myapp.sln /check cria a solução myapp e executa todas as verificações de compilação configuradas.

O SDK do .NET 9 inclui um pequeno número de verificações iniciais, por exemplo, BC0101 e BC0102. Para obter uma lista completa, consulte códigos BuildCheck .

Quando um problema é detetado, um diagnóstico é produzido na saída de compilação para o projeto que contém o problema.

Para obter mais informações, consulte a documentação do projeto .

Incompatibilidade do analisador

Muitos usuários instalam o SDK do .NET e o Visual Studio em cadências diferentes. Embora essa flexibilidade seja desejável, ela pode levar a problemas para ferramentas que precisam interoperar entre os dois ambientes. Um exemplo desse tipo de ferramenta é o Roslyn Analyzers. Os autores do analisador têm que codificar para versões específicas do Roslyn, mas quais versões estão disponíveis e quais são usadas por uma determinada compilação às vezes não está claro.

Esse tipo de incompatibilidade de versão entre o SDK do .NET e o MSBuild é conhecido como um SDK rasgado. Quando estiver neste estado, poderá ver erros como este:

CSC : aviso CS9057: O conjunto do analisador '..\dotnet\sdk\8.0.200\Sdks\Microsoft.NET.Sdk.Razor\source-generators\Microsoft.CodeAnalysis.Razor.Compiler.SourceGenerators.dll' faz referência à versão '4.9.0.0' do compilador, que é mais recente do que a versão atualmente em execução '4.8.0.0'.

O .NET 9 pode detetar e ajustar automaticamente para esse cenário de problema. A lógica MSBuild do SDK incorpora a versão do MSBuild fornecida e essas informações podem ser usadas para detetar quando o SDK está sendo executado em um ambiente com uma versão diferente. Quando isso acontece, o SDK insere um download implícito de um pacote de suporte chamado Microsoft.Net.Sdk.Compilers.Toolset que garante uma experiência de analisador consistente.

Conjuntos de carga de trabalho

Workload sets é um recurso SDK destinado a dar aos usuários mais controle sobre as cargas de trabalho que instalam e a cadência de alteração dessas cargas de trabalho. Nas versões anteriores, as cargas de trabalho eram atualizadas periodicamente à medida que novas versões de cargas de trabalho individuais eram lançadas em qualquer feed NuGet configurado. Agora, todas as de suas cargas de trabalho permanecem em uma versão única específica até que você faça um gesto explícito de atualização.

Você pode ver em que modo a sua instalação do SDK se encontra ao executar dotnet workload --info:

> dotnet workload --info
Workload version: 9.0.100-manifests.400dd185
Configured to use loose manifests when installing new manifests.
 [aspire]
   Installation Source: VS 17.10.35027.167, VS 17.11.35111.106
   Manifest Version:    8.0.2/8.0.100
   Manifest Path:       C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.aspire\8.0.2\WorkloadManifest.json
   Install Type:              Msi

Neste exemplo, a instalação do SDK está no modo 'manifesto', onde as atualizações são instaladas à medida que estão disponíveis. Para aceitar o novo modo, adicione uma opção --version a um comando dotnet workload install ou dotnet workload update. Você também pode controlar explicitamente seu modo de operação usando o novo comando dotnet workload config:

> dotnet workload config --update-mode workload-set
Successfully updated workload install mode to use workload-set.

Se você precisar alterar novamente por qualquer motivo, você pode executar o mesmo comando com manifests em vez de workload-set. Você também pode usar dotnet workload config --update-mode para verificar o modo de operação atual.

Para obter mais informações, consulte conjuntos de cargas de trabalho do .NET SDK.

Histórico da carga de trabalho

As cargas de trabalho do SDK do .NET são parte integrante do .NET MAUI e do Blazor WebAssembly. Em sua configuração padrão, você pode atualizar cargas de trabalho independentemente à medida que os autores de ferramentas .NET lançam novas versões. Além disso, as instalações do SDK do .NET feitas por meio do Visual Studio instalam um conjunto paralelo de versões. Sem tomar cuidado, o status de instalação da carga de trabalho de uma determinada instalação do SDK do .NET pode se desviar ao longo do tempo, mas não houve uma maneira de visualizar esse desvio.

Para resolver isso, o .NET 9 adiciona um novo comando dotnet workload history ao SDK do .NET. dotnet workload history imprime uma tabela histórica de instalações e modificações de carga de trabalho para a instalação atual do SDK do .NET. A tabela mostra a data da instalação ou modificação, o comando que foi executado, as cargas de trabalho que foram instaladas ou modificadas e as versões relevantes para o comando. Este resultado pode ajudá-lo a entender o desvio nas instalações de workload ao longo do tempo e ajudá-lo a tomar decisões informadas sobre quais versões de workloads deve configurar na sua instalação. Você pode pensar nisso como git reflog para cargas de trabalho.

> dotnet workload history

Id  Date                         Command       Workloads                                        Global.json Version  Workload Version
-----------------------------------------------------------------------------------------------------------------------------------------------
1   1/1/0001 12:00:00 AM +00:00  InitialState  android, ios, maccatalyst, maui-windows                               9.0.100-manifests.6d3c8f5d
2   9/4/2024 8:15:33 PM -05:00   install       android, aspire, ios, maccatalyst, maui-windows                       9.0.100-rc.1.24453.3

Neste exemplo, o SDK foi inicialmente instalado com as cargas de trabalho android, ios, maccatalyste maui-windows. Em seguida, o comando dotnet workload install aspire --version 9.0.100-rc.1.24453.3 foi utilizado para instalar a carga de trabalho aspire e mudar para o modo de conjuntos de carga de trabalho . Para retornar ao estado anterior, você pode usar o ID da primeira coluna na tabela de histórico, por exemplo, dotnet workload update --from-history 1.

Contentores

Suporte para publicação de registos inseguros

O suporte de publicação de contêiner interno do SDK pode publicar imagens em registros de contêiner. Até o .NET 9, esses registros precisavam ser protegidos — para que o SDK do .NET funcionasse, eles precisavam de suporte a HTTPS e certificados válidos. Os mecanismos de contêiner geralmente também podem ser configurados para trabalhar com registros inseguros, ou seja, registros que não têm TLS configurado ou têm TLS configurado com um certificado inválido. Este é um caso de uso válido, mas nossas ferramentas não suportam esse modo de comunicação.

A partir do .NET 9, o SDK pode se comunicar com registros inseguros.

Requisitos (dependendo do seu ambiente):

  • Configure a CLI do Docker para marcar um registro como inseguro.
  • Configure o Podman para marcar um registro como inseguro.
  • Use a variável de ambiente DOTNET_CONTAINER_INSECURE_REGISTRIES para passar uma lista delimitada por ponto-e-vírgula de domínios do Registro a serem tratados como inseguros.

Nomenclatura de variável de ambiente

As variáveis de ambiente que as ferramentas de publicação de contêiner usam para controlar alguns dos aspetos mais delicados da comunicação e segurança do Registro agora começam com o prefixo DOTNET em vez de SDK. O prefixo SDK continuará a ser suportado a curto prazo.

Análise de código

O .NET 9 inclui vários novos analisadores e fixadores de código para ajudar a verificar se você está usando APIs da biblioteca .NET de forma correta e eficiente. A tabela a seguir resume os novos analisadores.

ID da regra Categoria Descrição
CA1514: Evite o argumento de comprimento redundante Manutenibilidade Um argumento de comprimento explicitamente calculado pode ser propenso a erros e é desnecessário quando se está a cortar até ao final de uma string ou buffer.
CA1515: Considere tornar públicos os tipos internos Manutenibilidade Os tipos dentro de um assembly executável devem ser declarados como internal.
CA1871: Não passe uma struct anulável para 'ArgumentNullException.ThrowIfNull' Desempenho Para melhorar o desempenho, é melhor verificar a propriedade HasValue e gerar manualmente uma exceção do que passar uma estrutura anulável para ArgumentNullException.ThrowIfNull.
CA1872: Prefira 'Convert.ToHexString' e 'Convert.ToHexStringLower' ao invés de cadeias de chamadas baseadas em 'BitConverter.ToString' Desempenho Use Convert.ToHexString ou Convert.ToHexStringLower ao codificar bytes para uma representação de cadeia de caracteres hexadecimal.
CA2022: Evite leituras inexatas com Stream.Read Fiabilidade Uma chamada para Stream.Read pode retornar menos bytes do que o solicitado, resultando em código não confiável se o valor de retorno não for verificado.
CA2262: Definir 'MaxResponseHeadersLength' corretamente Utilização A propriedade HttpClientHandler.MaxResponseHeadersLength é medida em kilobytes, não em bytes.
CA2263: Prefira sobrecarga genérica quando o tipo é conhecido Utilização Sobrecargas genéricas são preferíveis a sobrecargas que aceitam um argumento do tipo System.Type quando o tipo é conhecido em tempo de compilação.
CA2264: Não passe um valor não anulável para 'ArgumentNullException.ThrowIfNull' Utilização Certas construções, como structs não anuláveis (exceto para Nullable<T>), expressões 'nameof()' e expressões 'novas' são conhecidas por nunca serem nulas, então ArgumentNullException.ThrowIfNull nunca lançará.
CA2265: Não compare Span<T> com nulo ou padrão Utilização Comparar um intervalo com null ou default pode não fazer o que tu pretendias. default e o null literal são implicitamente convertidos em Span<T>.Empty. Remova a comparação redundante ou torne o código mais explícito usando IsEmpty.