O que há de novo no .NET Core 3.0

Este artigo descreve o que há de novo no .NET Core 3.0. Uma das maiores melhorias é o suporte para aplicações de ambiente de trabalho do Windows (apenas Windows). Usando o componente SDK do .NET Core 3.0 Windows Desktop, você pode portar seus aplicativos Windows Forms e Windows Presentation Foundation (WPF). Para ser claro, o componente de área de trabalho do Windows só é suportado e incluído no Windows. Para obter mais informações, consulte a seção Área de trabalho do Windows mais adiante neste artigo.

O .NET Core 3.0 adiciona suporte para C# 8.0. É altamente recomendável que você use o Visual Studio 2019 versão 16.3 ou mais recente, ou o Visual Studio Code com a extensão C# mais recente.

Baixe e comece a usar o .NET Core 3.0 agora mesmo no Windows, macOS ou Linux.

Para obter mais informações sobre a versão, consulte o anúncio do .NET Core 3.0.

O .NET Core 3.0 RC 1 foi considerado pronto para produção pela Microsoft e foi totalmente suportado. Se estiver a utilizar uma versão de pré-visualização, tem de mudar para a versão RTM para continuar a oferecer suporte.

Melhorias de linguagem C# 8.0

O C# 8.0 também faz parte desta versão, que inclui o recurso de tipos de referência anuláveis, fluxos assíncronos e mais padrões. Para obter mais informações sobre os recursos do C# 8.0, consulte O que há de novo no C# 8.0.

Tutoriais relacionados aos recursos da linguagem C# 8.0:

Aprimoramentos de idioma foram adicionados para oferecer suporte aos seguintes recursos de API detalhados abaixo:

.NET Padrão 2.1

O .NET Core 3.0 implementa o .NET Standard 2.1. No entanto, o modelo padrão dotnet new classlib gera um projeto que ainda tem como alvo o .NET Standard 2.0. Para direcionar o .NET Standard 2.1, edite o arquivo de projeto e altere a TargetFramework propriedade para netstandard2.1:

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

  <PropertyGroup>
    <TargetFramework>netstandard2.1</TargetFramework>
  </PropertyGroup>

</Project>

Se você estiver usando o Visual Studio, precisará do Visual Studio 2019, pois o Visual Studio 2017 não oferece suporte ao .NET Standard 2.1 ou ao .NET Core 3.0.

Compilar/implantar

Executáveis padrão

O .NET Core agora cria executáveis dependentes da estrutura por padrão. Esse comportamento é novo para aplicativos que usam uma versão instalada globalmente do .NET Core. Anteriormente, apenas implantações independentes produziam um executável.

Durante dotnet build ou dotnet publish, é criado um executável (conhecido como appHost) que corresponde ao ambiente e à plataforma do SDK que você está usando. Você pode esperar as mesmas coisas com esses executáveis que faria com outros executáveis nativos, como:

  • Você pode clicar duas vezes no executável.
  • Você pode iniciar o aplicativo diretamente a partir de um prompt de comando, como myapp.exe no Windows, Linux e ./myapp macOS.

macOS appHost e reconhecimento de firma

Apenas macOS

A partir do .NET Core SDK 3.0 para macOS, a configuração para produzir um executável padrão (conhecido como appHost) é desabilitada por padrão. Para obter mais informações, consulte macOS Catalina Notarization e o impacto nos downloads e projetos do .NET Core.

Quando a configuração appHost está habilitada, o .NET Core gera um executável Mach-O nativo quando você cria ou publica. Seu aplicativo é executado no contexto do appHost quando é executado a partir do código-fonte com o dotnet run comando ou iniciando o executável Mach-O diretamente.

Sem o appHost, a única maneira de um usuário iniciar um aplicativo dependente da estrutura é com o dotnet <filename.dll> comando. Um appHost é sempre criado quando você publica seu aplicativo independente.

Você pode configurar o appHost no nível do projeto ou alternar o appHost para um comando específico dotnet com o -p:UseAppHost parâmetro:

  • Ficheiro de projeto

    <PropertyGroup>
      <UseAppHost>true</UseAppHost>
    </PropertyGroup>
    
  • Parâmetro de linha de comando

    dotnet run -p:UseAppHost=true
    

Para obter mais informações sobre a UseAppHost configuração, consulte Propriedades do MSBuild para Microsoft.NET.Sdk.

Executáveis de arquivo único

O dotnet publish comando oferece suporte ao empacotamento de seu aplicativo em um executável de arquivo único específico da plataforma. O executável é de extração automática e contém todas as dependências (inclusive nativas) necessárias para executar seu aplicativo. Quando o aplicativo é executado pela primeira vez, o aplicativo é extraído para um diretório com base no nome do aplicativo e no identificador de compilação. A inicialização é mais rápida quando o aplicativo é executado novamente. O aplicativo não precisa se extrair uma segunda vez, a menos que uma nova versão tenha sido usada.

Para publicar um executável de arquivo único, defina o PublishSingleFile em seu projeto ou na linha de comando com o dotnet publish comando:

<PropertyGroup>
  <RuntimeIdentifier>win10-x64</RuntimeIdentifier>
  <PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>

-or-

dotnet publish -r win10-x64 -p:PublishSingleFile=true

Para obter mais informações sobre publicação de arquivo único, consulte o documento de design do empacotador de arquivo único.

Corte de montagem

O SDK do .NET core 3.0 vem com uma ferramenta que pode reduzir o tamanho dos aplicativos analisando IL e cortando assemblies não utilizados.

Os aplicativos independentes incluem tudo o que é necessário para executar seu código, sem exigir que o .NET seja instalado no computador host. No entanto, muitas vezes o aplicativo requer apenas um pequeno subconjunto da estrutura para funcionar, e outras bibliotecas não utilizadas podem ser removidas.

O .NET Core agora inclui uma configuração que usará a ferramenta IL Trimmer para verificar a IL do seu aplicativo. Esta ferramenta deteta o código necessário e, em seguida, corta bibliotecas não utilizadas. Essa ferramenta pode reduzir significativamente o tamanho da implantação de alguns aplicativos.

Para habilitar essa ferramenta, adicione a <PublishTrimmed> configuração em seu projeto e publique um aplicativo independente:

<PropertyGroup>
  <PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
dotnet publish -r <rid> -c Release

Como exemplo, o novo modelo de projeto de console básico "hello world" que está incluído, quando publicado, atinge cerca de 70 MB de tamanho. <PublishTrimmed>Usando o , esse tamanho é reduzido para cerca de 30 MB.

É importante considerar que aplicativos ou estruturas (incluindo ASP.NET Core e WPF) que usam reflexão ou recursos dinâmicos relacionados, geralmente quebram quando cortados. Essa quebra ocorre porque o aparador não sabe sobre esse comportamento dinâmico e não pode determinar quais tipos de estrutura são necessários para reflexão. A ferramenta IL Trimmer pode ser configurada para estar ciente desse cenário.

Acima de tudo, certifique-se de testar seu aplicativo após o corte.

Para obter mais informações sobre a ferramenta IL Trimmer, consulte a documentação ou visite o repositório mono/linker.

Compilação hierárquica

A compilação hierárquica (TC) está ativada por padrão com o .NET Core 3.0. Esse recurso permite que o tempo de execução use mais adaptativamente o compilador just-in-time (JIT) para obter um melhor desempenho.

O principal benefício da compilação hierárquica é fornecer duas maneiras de métodos de jitting: em uma camada de qualidade inferior, mas mais rápida, ou em uma camada de qualidade mais alta, mas mais lenta. A qualidade refere-se a quão bem o método é otimizado. O TC ajuda a melhorar o desempenho de um aplicativo à medida que ele passa por vários estágios de execução, desde a inicialização até o estado estacionário. Quando a compilação hierárquica é desativada, cada método é compilado de uma única maneira que é tendenciosa para o desempenho de estado estacionário sobre o desempenho de inicialização.

Quando o TC está habilitado, o seguinte comportamento se aplica à compilação de método quando um aplicativo é iniciado:

  • Se o método tiver código compilado antecipadamente, ou ReadyToRun, o código pré-gerado será usado.
  • Caso contrário, o método é jitted. Normalmente, esses métodos são genéricos sobre tipos de valor.
    • O Quick JIT produz código de qualidade inferior (ou menos otimizado) mais rapidamente. No .NET Core 3.0, o JIT Rápido é habilitado por padrão para métodos que não contêm loops e é preferido durante a inicialização.
    • O JIT totalmente otimizado produz código de maior qualidade (ou mais otimizado) mais lentamente. Para métodos em que o JIT rápido não seria usado (por exemplo, se o método for atribuído com MethodImplOptions.AggressiveOptimization), o JIT totalmente otimizado é usado.

Para métodos frequentemente chamados, o compilador just-in-time eventualmente cria código totalmente otimizado em segundo plano. O código otimizado substitui o código pré-compilado para esse método.

O código gerado pelo Quick JIT pode ser executado mais lentamente, alocar mais memória ou usar mais espaço de pilha. Se houver problemas, você pode desabilitar o JIT rápido usando esta propriedade MSBuild no arquivo de projeto:

<PropertyGroup>
  <TieredCompilationQuickJit>false</TieredCompilationQuickJit>
</PropertyGroup>

Para desativar completamente o TC, use esta propriedade MSBuild em seu arquivo de projeto:

<PropertyGroup>
  <TieredCompilation>false</TieredCompilation>
</PropertyGroup>

Gorjeta

Se você alterar essas configurações no arquivo de projeto, talvez seja necessário executar uma compilação limpa para que as novas configurações sejam refletidas (exclua os obj diretórios e bin e reconstrua).

Para obter mais informações sobre como configurar a compilação em tempo de execução, consulte Opções de configuração de tempo de execução para compilação.

Imagens ReadyToRun

Você pode melhorar o tempo de inicialização do seu aplicativo .NET Core compilando seus assemblies de aplicativo como formato ReadyToRun (R2R). R2R é uma forma de compilação ahead-of-time (AOT).

Os binários R2R melhoram o desempenho de inicialização reduzindo a quantidade de trabalho que o compilador just-in-time (JIT) precisa fazer enquanto seu aplicativo é carregado. Os binários contêm código nativo semelhante em comparação com o que o JIT produziria. No entanto, os binários R2R são maiores porque contêm código de linguagem intermediária (IL), que ainda é necessário para alguns cenários, e a versão nativa do mesmo código. O R2R só está disponível quando você publica um aplicativo autônomo destinado a ambientes de tempo de execução específicos (RID), como Linux x64 ou Windows x64.

Para compilar seu projeto como ReadyToRun, faça o seguinte:

  1. Adicione a <PublishReadyToRun> configuração ao seu projeto:

    <PropertyGroup>
      <PublishReadyToRun>true</PublishReadyToRun>
    </PropertyGroup>
    
  2. Publique um aplicativo independente. Por exemplo, este comando cria um aplicativo independente para a versão de 64 bits do Windows:

    dotnet publish -c Release -r win-x64 --self-contained
    

Restrições entre plataformas/arquitetura

Atualmente, o compilador ReadyToRun não oferece suporte a direcionamento cruzado. Você deve compilar em um determinado destino. Por exemplo, se você quiser imagens R2R para Windows x64, precisará executar o comando publish nesse ambiente.

Exceções à segmentação cruzada:

  • O Windows x64 pode ser usado para compilar imagens do Windows Arm32, Arm64 e x86.
  • O Windows x86 pode ser usado para compilar imagens do Windows Arm32.
  • Linux x64 pode ser usado para compilar imagens Linux Arm32 e Arm64.

Para obter mais informações, consulte Pronto para executar.

Tempo de execução/SDK

Roll-forward do tempo de execução da versão principal

O .NET Core 3.0 introduz um recurso de aceitação que permite que seu aplicativo avance para a versão principal mais recente do .NET Core. Além disso, uma nova configuração foi adicionada para controlar como o roll forward é aplicado ao seu aplicativo. Isso pode ser configurado das seguintes maneiras:

  • Propriedade do arquivo de projeto: RollForward
  • Propriedade do arquivo de configuração de tempo de execução: rollForward
  • Variável de ambiente: DOTNET_ROLL_FORWARD
  • Argumento de linha de comando: --roll-forward

Um dos seguintes valores deve ser especificado. Se a configuração for omitida, Minor será o padrão.

  • LatestPatch
    Avançar para a versão de patch mais alta. Isso desativa o roll forward da versão secundária.
  • Menor
    Avançar para a versão secundária superior mais baixa, se a versão secundária solicitada estiver ausente. Se a versão secundária solicitada estiver presente, a política LatestPatch será usada.
  • Major:
    Avançar para a versão principal superior mais baixa e a versão secundária mais baixa, se a versão principal solicitada estiver ausente. Se a versão principal solicitada estiver presente, a política Secundária será usada.
  • Mais recenteMinor
    Avançar para a versão secundária mais alta, mesmo que a versão secundária solicitada esteja presente. Destinado a cenários de hospedagem de componentes.
  • Mais recenteMajor
    Avançar para a versão principal mais alta e a versão secundária mais alta, mesmo que a versão principal solicitada esteja presente. Destinado a cenários de hospedagem de componentes.
  • Desativar
    Não role para a frente. Vincular somente à versão especificada. Esta política não é recomendada para uso geral porque desativa a capacidade de avançar para os patches mais recentes. Este valor só é recomendado para testes.

Além da configuração Desativar , todas as configurações usarão a versão de patch mais alta disponível.

Por padrão, se a versão solicitada (conforme especificado no .runtimeconfig.json aplicativo) for uma versão de lançamento, somente as versões de lançamento serão consideradas para roll forward. Todas as versões de pré-lançamento são ignoradas. Se não houver uma versão de lançamento correspondente, as versões de pré-lançamento serão levadas em consideração. Esse comportamento pode ser alterado pela configuração DOTNET_ROLL_FORWARD_TO_PRERELEASE=1, caso em que todas as versões são sempre consideradas.

Criar dependências de cópias

O dotnet build comando agora copia as dependências do NuGet para seu aplicativo do cache do NuGet para a pasta de saída de compilação. Anteriormente, as dependências eram copiadas apenas como parte do dotnet publish.

Existem algumas operações, como corte e publicação de páginas de barbear, que ainda exigirão publicação.

Ferramentas locais

O .NET Core 3.0 apresenta ferramentas locais. As ferramentas locais são semelhantes às ferramentas globais, mas estão associadas a um local específico no disco. As ferramentas locais não estão disponíveis globalmente e são distribuídas como pacotes NuGet.

As ferramentas locais dependem de um nome dotnet-tools.json de arquivo de manifesto no diretório atual. Esse arquivo de manifesto define as ferramentas a serem disponibilizadas nessa pasta e abaixo. Você pode distribuir o arquivo de manifesto com seu código para garantir que qualquer pessoa que trabalhe com seu código possa restaurar e usar as mesmas ferramentas.

Para ferramentas globais e locais, é necessária uma versão compatível do tempo de execução. Muitas ferramentas atualmente em NuGet.org destino .NET Core Runtime 2.1. Para instalar essas ferramentas globalmente ou localmente, você ainda precisaria instalar o NET Core 2.1 Runtime.

Novas opções de global.json

O arquivo global.json tem novas opções que fornecem mais flexibilidade quando você está tentando definir qual versão do SDK do .NET Core é usada. As novas opções são:

  • allowPrerelease: Indica se o resolvedor do SDK deve considerar as versões de pré-lançamento ao selecionar a versão do SDK a ser usada.
  • rollForward: Indica a política de roll-forward a ser usada ao selecionar uma versão do SDK, seja como um fallback quando uma versão específica do SDK estiver ausente ou como uma diretiva para usar uma versão superior.

Para obter mais informações sobre as alterações, incluindo valores padrão, valores suportados e novas regras de correspondência, consulte global.json visão geral.

Tamanhos menores de pilha de coleta de lixo

O tamanho de heap padrão do Garbage Collector foi reduzido, resultando no .NET Core usando menos memória. Essa alteração se alinha melhor com o orçamento de alocação da geração 0 com os tamanhos modernos de cache do processador.

Suporte de página grande para coleta de lixo

Large Pages (também conhecido como Huge Pages no Linux) é um recurso onde o sistema operacional é capaz de estabelecer regiões de memória maiores do que o tamanho da página nativa (geralmente 4K) para melhorar o desempenho do aplicativo que solicita essas páginas grandes.

O Coletor de Lixo agora pode ser configurado com a configuração GCLargePages como um recurso de aceitação para optar por alocar páginas grandes no Windows.

Área de trabalho do Windows & COM

Instalador do Windows SDK do .NET Core

O instalador MSI para Windows foi alterado a partir do .NET Core 3.0. Os instaladores do SDK agora atualizarão as versões de banda de recursos do SDK no local. As bandas de recursos são definidas nos grupos de centenas na seção de patch do número da versão. Por exemplo, 3.0.101 e 3.0.201 são versões em duas bandas de recursos diferentes, enquanto 3.0.101 e 3.0.199 estão na mesma faixa de recursos. E, quando o .NET Core SDK 3.0.101 está instalado, .NET Core SDK 3.0.100 serão removidos da máquina, se existir. Quando o .NET Core SDK 3.0.200 é instalado na mesma máquina, .NET Core SDK 3.0.O 101 não será removido.

Para obter mais informações sobre controle de versão, consulte Visão geral de como o .NET Core é versionado.

Ambiente de trabalho do Windows

O .NET Core 3.0 oferece suporte a aplicativos da área de trabalho do Windows usando o Windows Presentation Foundation (WPF) e o Windows Forms. Essas estruturas também oferecem suporte ao uso de controles modernos e estilo Fluent da Biblioteca XAML da interface do usuário do Windows (WinUI) por meio de ilhas XAML.

O componente Área de Trabalho do Windows faz parte do SDK do Windows .NET Core 3.0.

Você pode criar um novo aplicativo WPF ou Windows Forms com os seguintes dotnet comandos:

dotnet new wpf
dotnet new winforms

O Visual Studio 2019 adiciona novos modelos de projeto para .NET Core 3.0, Windows Forms e WPF.

Para obter mais informações sobre como portar um aplicativo .NET Framework existente, consulte Porta de projetos WPF e Porta de projetos do Windows Forms.

WinForms DPI alto

Os aplicativos .NET Core Windows Forms podem definir o modo de alto DPI com Application.SetHighDpiMode(HighDpiMode)o . O SetHighDpiMode método define o modo DPI alto correspondente, a menos que a configuração tenha sido definida por outros meios, como App.Manifest ou P/Invoke antes de Application.Run.

Os valores possíveis highDpiMode , expressos pelo enum System.Windows.Forms.HighDpiMode , são:

  • DpiUnaware
  • SystemAware
  • PerMonitor
  • PerMonitorV2
  • DpiUnawareGdiScaled

Para obter mais informações sobre modos de alto DPI, consulte High DPI Desktop Application Development on Windows.

Criar componentes COM

No Windows, agora você pode criar componentes gerenciados chamáveis COM. Esse recurso é fundamental para usar o .NET Core com modelos de suplemento COM e também para fornecer paridade com o .NET Framework.

Ao contrário do .NET Framework, onde o mscoree.dll foi usado como o servidor COM, o .NET Core adicionará uma dll de iniciador nativo ao diretório bin quando você criar seu componente COM.

Para obter um exemplo de como criar um componente COM e consumi-lo, consulte a demonstração COM.

Interoperabilidade nativa do Windows

O Windows oferece uma API nativa avançada na forma de APIs C simples, COM e WinRT. Enquanto o .NET Core suporta P/Invoke, o .NET Core 3.0 adiciona a capacidade de CoCriar APIs COM e Ativar APIs do WinRT. Para obter um exemplo de código, consulte a demonstração do Excel.

Implantação do MSIX

MSIX é um novo formato de pacote de aplicativos do Windows. Ele pode ser usado para implantar aplicativos de desktop .NET Core 3.0 no Windows 10.

O Windows Application Packaging Project, disponível no Visual Studio 2019, permite criar pacotes MSIX com aplicativos .NET Core autônomos .

O arquivo de projeto .NET Core deve especificar os tempos de execução suportados na <RuntimeIdentifiers> propriedade:

<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>

Melhorias no Linux

SerialPort para Linux

O .NET Core 3.0 fornece suporte básico para System.IO.Ports.SerialPort Linux.

Anteriormente, o .NET Core só suportava o uso SerialPort no Windows.

Para obter mais informações sobre o suporte limitado para a porta serial no Linux, consulte a edição #33146 do GitHub.

Limites de memória do Docker e do cgroup

Executar o .NET Core 3.0 no Linux com o Docker funciona melhor com limites de memória cgroup. A execução de um contêiner do Docker com limites de memória, como com docker run -m, altera o comportamento do .NET Core.

  • Tamanho de heap padrão do coletor de lixo (GC): máximo de 20 mb ou 75% do limite de memória no contêiner.
  • O tamanho explícito pode ser definido como um número absoluto ou porcentagem do limite de cgroup.
  • O tamanho mínimo do segmento reservado por pilha GC é de 16 mb. Esse tamanho reduz o número de pilhas criadas em máquinas.

Suporte GPIO para Raspberry Pi

Dois pacotes foram lançados para o NuGet que você pode usar para programação GPIO:

Os pacotes GPIO incluem APIs para dispositivos GPIO, SPI, I2C e PWM. O pacote de ligações IoT inclui associações de dispositivo. Para obter mais informações, consulte o repositório GitHub de dispositivos.

Suporte a Linux Arm64

O .NET Core 3.0 adiciona suporte para Arm64 para Linux. O principal caso de uso do Arm64 é atualmente com cenários de IoT. Para obter mais informações, consulte Status do .NET Core Arm64.

As imagens do Docker para .NET Core no Arm64 estão disponíveis para Alpine, Debian e Ubuntu.

Nota

O suporte para os sistemas operacionais macOS Arm64 (ou "Apple Silicon") e Windows Arm64 foi posteriormente adicionado no .NET 6.

Segurança

TLS 1.3 & OpenSSL 1.1.1 no Linux

O .NET Core agora aproveita o suporte a TLS 1.3 no OpenSSL 1.1.1, quando ele está disponível em um determinado ambiente. Com TLS 1.3:

  • Os tempos de conexão são melhorados com viagens de ida e volta reduzidas necessárias entre o cliente e o servidor.
  • Segurança melhorada devido à remoção de vários algoritmos criptográficos obsoletos e inseguros.

Quando disponível, o .NET Core 3.0 usa OpenSSL 1.1.1, OpenSSL 1.1.0 ou OpenSSL 1.0.2 em um sistema Linux. Quando o OpenSSL 1.1.1 estiver disponível, ambos os System.Net.Security.SslStream tipos usarão System.Net.Http.HttpClient o TLS 1.3 (assumindo que o cliente e o servidor suportam o TLS 1.3).

O exemplo C# 8.0 a seguir demonstra o .NET Core 3.0 no Ubuntu 18.10 conectando-se a https://www.cloudflare.com:

using System;
using System.Net.Security;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace whats_new
{
    public static class TLS
    {
        public static async Task ConnectCloudFlare()
        {
            var targetHost = "www.cloudflare.com";

            using TcpClient tcpClient = new TcpClient();

            await tcpClient.ConnectAsync(targetHost, 443);

            using SslStream sslStream = new SslStream(tcpClient.GetStream());

            await sslStream.AuthenticateAsClientAsync(targetHost);
            await Console.Out.WriteLineAsync($"Connected to {targetHost} with {sslStream.SslProtocol}");
        }
    }
}

Cifras de criptografia

O .NET Core 3.0 adiciona suporte para cifras AES-GCM e AES-CCM , implementadas com System.Security.Cryptography.AesGcm e System.Security.Cryptography.AesCcm respectivamente. Esses algoritmos são ambos algoritmos de criptografia autenticada com dados de associação (AEAD).

O código a seguir demonstra o uso da AesGcm cifra para criptografar e descriptografar dados aleatórios.

using System;
using System.Linq;
using System.Security.Cryptography;

namespace whats_new
{
    public static class Cipher
    {
        public static void Run()
        {
            // key should be: pre-known, derived, or transported via another channel, such as RSA encryption
            byte[] key = new byte[16];
            RandomNumberGenerator.Fill(key);

            byte[] nonce = new byte[12];
            RandomNumberGenerator.Fill(nonce);

            // normally this would be your data
            byte[] dataToEncrypt = new byte[1234];
            byte[] associatedData = new byte[333];
            RandomNumberGenerator.Fill(dataToEncrypt);
            RandomNumberGenerator.Fill(associatedData);

            // these will be filled during the encryption
            byte[] tag = new byte[16];
            byte[] ciphertext = new byte[dataToEncrypt.Length];

            using (AesGcm aesGcm = new AesGcm(key))
            {
                aesGcm.Encrypt(nonce, dataToEncrypt, ciphertext, tag, associatedData);
            }

            // tag, nonce, ciphertext, associatedData should be sent to the other part

            byte[] decryptedData = new byte[ciphertext.Length];

            using (AesGcm aesGcm = new AesGcm(key))
            {
                aesGcm.Decrypt(nonce, ciphertext, tag, decryptedData, associatedData);
            }

            // do something with the data
            // this should always print that data is the same
            Console.WriteLine($"AES-GCM: Decrypted data is {(dataToEncrypt.SequenceEqual(decryptedData) ? "the same as" : "different than")} original data.");
        }
    }
}

Importação/exportação de chave criptográfica

O .NET Core 3.0 suporta a importação e exportação de chaves públicas e privadas assimétricas de formatos padrão. Você não precisa usar um certificado X.509.

Todos os tipos de chave, como RSA, DSA, ECDsa e ECDiffieHellman, suportam os seguintes formatos:

  • Chave Pública

    • X.509 AssuntoPublicKeyInfo
  • Chave privada

    • PKCS#8 PrivateKeyInfo
    • PKCS#8 EncryptedPrivateKeyInfo

As chaves RSA também suportam:

  • Chave Pública

    • PKCS#1 RSAPublicKey
  • Chave privada

    • PKCS#1 RSAPrivateKey

Os métodos de exportação produzem dados binários codificados por DER e os métodos de importação esperam o mesmo. Se uma chave for armazenada no formato PEM de texto amigável, o chamador precisará basear64-decodificar o conteúdo antes de chamar um método de importação.

using System;
using System.Security.Cryptography;

namespace whats_new
{
    public static class RSATest
    {
        public static void Run(string keyFile)
        {
            using var rsa = RSA.Create();

            byte[] keyBytes = System.IO.File.ReadAllBytes(keyFile);
            rsa.ImportRSAPrivateKey(keyBytes, out int bytesRead);

            Console.WriteLine($"Read {bytesRead} bytes, {keyBytes.Length - bytesRead} extra byte(s) in file.");
            RSAParameters rsaParameters = rsa.ExportParameters(true);
            Console.WriteLine(BitConverter.ToString(rsaParameters.D));
        }
    }
}

Os arquivos PKCS#8 podem ser inspecionados e System.Security.Cryptography.Pkcs.Pkcs8PrivateKeyInfo os arquivos PFX/PKCS#12 podem ser inspecionados com System.Security.Cryptography.Pkcs.Pkcs12Info. Os ficheiros PFX/PKCS#12 podem ser manipulados com System.Security.Cryptography.Pkcs.Pkcs12Builder.

Alterações na API do .NET Core 3.0

Intervalos e índices

O novo System.Index tipo pode ser usado para indexação. Você pode criar um a partir de um int que conta desde o início, ou com um operador de prefixo ^ (C#) que conta a partir do fim:

Index i1 = 3;  // number 3 from beginning
Index i2 = ^4; // number 4 from end
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine($"{a[i1]}, {a[i2]}"); // "3, 6"

Há também o System.Range tipo, que consiste em dois Index valores, um para o início e outro para o fim, e pode ser escrito com uma x..y expressão de intervalo (C#). Em seguida, você pode indexar com um Range, que produz uma fatia:

var slice = a[i1..i2]; // { 3, 4, 5 }

Para obter mais informações, consulte o tutorial de intervalos e índices.

Fluxos assíncronos

O IAsyncEnumerable<T> tipo é uma nova versão assíncrona do IEnumerable<T>. A linguagem permite que você await foreach IAsyncEnumerable<T> consuma seus elementos e use yield return para produzir elementos.

O exemplo a seguir demonstra a produção e o consumo de fluxos assíncronos. A foreach instrução é assíncrona e é usada yield return para produzir um fluxo assíncrono para chamadores. Este padrão (usando yield return) é o modelo recomendado para produzir fluxos assíncronos.

async IAsyncEnumerable<int> GetBigResultsAsync()
{
    await foreach (var result in GetResultsAsync())
    {
        if (result > 20) yield return result;
    }
}

Além de poder await foreachcriar iteradores assíncronos, por exemplo, um iterador que retorna um IAsyncEnumerable/IAsyncEnumerator que você pode tanto await yield quanto em. Para objetos que precisam ser descartados, você pode usar IAsyncDisposable, que vários tipos de BCL implementam, como Stream e Timer.

Para obter mais informações, consulte o tutorial de fluxos assíncronos.

Ponto flutuante IEEE

As APIs de ponto flutuante estão sendo atualizadas para estar em conformidade com a revisão IEEE 754-2008. O objetivo dessas alterações é expor todas as operações necessárias e garantir que elas estejam em conformidade comportamental com a especificação IEEE. Para obter mais informações sobre melhorias de ponto flutuante, consulte a postagem do blog Análise de ponto flutuante e melhorias de formatação no .NET Core 3.0 .

As correções de análise e formatação incluem:

  • Analise e arredondar corretamente entradas de qualquer comprimento.
  • Analise e formate corretamente o zero negativo.
  • Analise Infinity corretamente e NaN faça uma verificação sem diferenciação de maiúsculas e minúsculas e permita um anterior + opcional, quando aplicável.

As novas System.Math APIs incluem:

  • BitIncrement(Double) e BitDecrement(Double)
    Corresponde às nextUp operações e nextDown IEEE. Eles retornam o menor número de ponto flutuante que compara maior ou menor do que a entrada (respectivamente). Por exemplo, Math.BitIncrement(0.0) retornaria double.Epsilon.

  • MaxMagnitude(Double, Double) e MinMagnitude(Double, Double)
    Corresponde às maxNumMag operações IEEE e minNumMag IEEE, elas retornam o valor que é maior ou menor em magnitude das duas entradas (respectivamente). Por exemplo, Math.MaxMagnitude(2.0, -3.0) retornaria -3.0.

  • ILogB(Double)
    Corresponde à logB operação IEEE que retorna um valor integral, ele retorna o log integral base-2 do parâmetro de entrada. Este método é efetivamente o mesmo que floor(log2(x)), mas feito com erro mínimo de arredondamento.

  • ScaleB(Double, Int32)
    Corresponde à scaleB operação IEEE que leva um valor integral, retorna efetivamente x * pow(2, n), mas é feita com erro mínimo de arredondamento.

  • Log2(Double)
    Corresponde à log2 operação IEEE, ele retorna o logaritmo de base-2. Minimiza o erro de arredondamento.

  • FusedMultiplyAdd(Double, Double, Double)
    Corresponde à fma operação IEEE, ele executa uma adição de multiplicação fundida. Ou seja, ele faz (x * y) + z como uma única operação, minimizando assim o erro de arredondamento. Um exemplo é FusedMultiplyAdd(1e308, 2.0, -1e308), que retorna 1e308. O regular (1e308 * 2.0) - 1e308 retorna double.PositiveInfinity.

  • CopySign(Double, Double)
    Corresponde à copySign operação IEEE, ele retorna o valor de x, mas com o sinal de y.

Intrínsecos dependentes da plataforma .NET

Foram adicionadas APIs que permitem o acesso a determinadas instruções de CPU orientadas a perf, como os conjuntos de instruções SIMD ou Bit Manipulation. Essas instruções podem ajudar a obter melhorias significativas de desempenho em determinados cenários, como o processamento eficiente de dados em paralelo.

Quando apropriado, as bibliotecas .NET começaram a usar essas instruções para melhorar o desempenho.

Para obter mais informações, consulte .NET Platform-Dependent Intrinsics.

APIs de versão do .NET Core aprimoradas

A partir do .NET Core 3.0, as APIs de versão fornecidas com o .NET Core agora retornam as informações esperadas. Por exemplo:

System.Console.WriteLine($"Environment.Version: {System.Environment.Version}");

// Old result
//   Environment.Version: 4.0.30319.42000
//
// New result
//   Environment.Version: 3.0.0
System.Console.WriteLine($"RuntimeInformation.FrameworkDescription: {System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription}");

// Old result
//   RuntimeInformation.FrameworkDescription: .NET Core 4.6.27415.71
//
// New result (notice the value includes any preview release information)
//   RuntimeInformation.FrameworkDescription: .NET Core 3.0.0-preview4-27615-11

Aviso

Quebrando a mudança. Esta é tecnicamente uma mudança de quebra porque o esquema de versionamento mudou.

Suporte JSON integrado rápido

Os usuários do .NET confiaram em grande parte no Newtonsoft.Json e em outras bibliotecas JSON populares, que continuam a ser boas escolhas. Newtonsoft.Json usa cadeias de caracteres .NET como seu tipo de dados base, que é UTF-16 sob o capô.

O novo suporte JSON integrado é de alto desempenho, baixa alocação e funciona com texto JSON codificado em UTF-8. Para obter mais informações sobre o namespace e tipos System.Text.Json , consulte os seguintes artigos:

Suporte HTTP/2

O System.Net.Http.HttpClient tipo suporta o protocolo HTTP/2. Se HTTP/2 estiver habilitado, a versão do protocolo HTTP será negociada via TLS/ALPN e HTTP/2 será usado se o servidor optar por usá-lo.

O protocolo padrão permanece HTTP/1.1, mas HTTP/2 pode ser habilitado de duas maneiras diferentes. Primeiro, você pode definir a mensagem de solicitação HTTP para usar HTTP/2:

var client = new HttpClient() { BaseAddress = new Uri("https://localhost:5001") };

// HTTP/1.1 request
using (var response = await client.GetAsync("/"))
    Console.WriteLine(response.Content);

// HTTP/2 request
using (var request = new HttpRequestMessage(HttpMethod.Get, "/") { Version = new Version(2, 0) })
using (var response = await client.SendAsync(request))
    Console.WriteLine(response.Content);

Em segundo lugar, você pode mudar HttpClient para usar HTTP/2 por padrão:

var client = new HttpClient()
{
    BaseAddress = new Uri("https://localhost:5001"),
    DefaultRequestVersion = new Version(2, 0)
};

// HTTP/2 is default
using (var response = await client.GetAsync("/"))
    Console.WriteLine(response.Content);

Muitas vezes, ao desenvolver um aplicativo, você deseja usar uma conexão não criptografada. Se você souber que o ponto de extremidade de destino usará HTTP/2, poderá ativar conexões não criptografadas para HTTP/2. Você pode ativá-lo definindo a DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2UNENCRYPTEDSUPPORT variável de ambiente como 1 ou habilitando-a no contexto do aplicativo:

AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

Próximos passos