Novidades do .NET Core 3.0

Este artigo descreve o que há de novo no .NET Core 3,0. Um dos maiores avanços é o suporte para aplicativos Windows de área de trabalho (somente Windows). Usando a Área de Trabalho do Windows do componente de SDK do .NET Core 3.0, você pode portar seus aplicativos Windows Forms e WPF (Windows Presentation Foundation). Para deixar claro, o componente Windows Desktop só é compatível com o Windows e só é incluído nele. 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 Visual Studio 2019 versão 16,3 ou mais recente, Visual Studio para Mac 8,3 ou mais recente ou Visual Studio Code com a extensão C# mais recente.

baixe e comece a usar o .net Core 3,0 agora em 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 como pronto para produção pela Microsoft e foi totalmente suportado. Se você estiver usando uma versão de visualização, deverá mover para a versão RTM para obter suporte contínuo.

Aprimoramentos na 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ável , fluxos assíncronos e mais padrões. Para obter mais informações sobre recursos do C# 8.0, consulte Novidades do C# 8.0.

Tutoriais relacionados aos recursos de linguagem C# 8,0:

Foram adicionados aprimoramentos de linguagem para dar suporte aos seguintes recursos de API detalhados abaixo:

.NET Standard 2.1

O .NET Core 3,0 implementa .NET Standard 2,1. No entanto, o dotnet new classlib modelo padrão gera um projeto que ainda tem como alvo .net Standard 2,0. Para direcionar ao .NET Standard 2.1, edite seu arquivo de projeto e altere a propriedade TargetFramework 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, já que o Visual Studio 2017 não dá suporte ao .NET Standard 2.1 nem ao .NET Core 3.0.

Compilar/implantar

Executáveis por padrão

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

Durante dotnet build ou dotnet publish , um executável (conhecido como appHost) é criado que corresponde ao ambiente e à plataforma do SDK que você está usando. Você pode esperar desses executáveis o mesmo que de outros executáveis nativos, como:

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

macOS appHost e notarization

Somente macOS

A partir do notarized SDK do .NET Core 3,0 para macOS, a configuração para produzir um executável padrão (conhecida como appHost) é desabilitada por padrão. Para obter mais informações, consulte o notarization Catalina do MacOS e o impacto sobre os downloads e projetos do .NET Core.

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

Sem o appHost, a única maneira como um usuário pode 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 dotnet comando específico com o -p:UseAppHost parâmetro:

  • Arquivo 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 de MSBuild para Microsoft. NET. Sdk.

Executáveis de arquivo único

O comando dotnet publish dá suporte ao empacotamento de seu aplicativo em um executável de arquivo único específico da plataforma. O executável é autoextraível e contém todas as dependências (incluindo nativas) necessárias para a execução do 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 do build. A inicialização é mais rápida quando o aplicativo é executado novamente. O aplicativo não precisará autoextrair uma segunda vez, a menos que uma versão nova tenha sido usada.

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

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

- ou -

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

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

Corte de assembly

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

Os aplicativos autossuficientes incluem todos os componentes necessários 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.

Agora, o .NET Core inclui uma configuração que usará a ferramenta de corte Il para verificar o Il do seu aplicativo. Essa ferramenta detecta o código necessário e, em seguida, corta as bibliotecas não utilizadas. Ela pode reduzir significativamente o tamanho da implantação de alguns aplicativos.

Para habilitá-la, adicione a configuração <PublishTrimmed> ao seu projeto e publique um aplicativo autossuficiente:

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

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

É importante considerar que os aplicativos ou estruturas (incluindo ASP.NET Core e WPF) que usam reflexão ou recursos dinâmicos relacionados, geralmente são interrompidos quando cortados. Essa quebra ocorre porque o corte 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 de corte de IL pode ser configurada para estar ciente desse cenário.

Antes de mais nada, teste seu aplicativo depois de cortar.

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

Compilação em camadas

A TC (compilação em camadas) está ativa por padrão com o .NET Core 3.0. Esse recurso permite que o tempo de execução use de forma mais adaptável o compilador JIT (just-in-time) para obter um melhor desempenho.

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

Quando TC está habilitado, o comportamento a seguir se aplica à compilação do método quando um aplicativo é inicializado:

  • Se o método tiver código com compilação antecipada de tempo ou ReadyToRun, o código gerado previamente será usado.
  • Caso contrário, o método é JIT. Normalmente, esses métodos são genéricos sobre tipos de valor.
    • O Quick JIT produz código mais rápido (ou menos otimizado) com mais rapidez. No .NET Core 3,0, o JIT rápido é habilitado por padrão para métodos que não contêm loops e são preferenciais durante a inicialização.
    • O JIT de Otimização total produz um código de qualidade mais alta (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 de Otimização total será usado.

Para métodos chamados com frequência, o compilador just-in-time, eventualmente, cria código totalmente otimizado em segundo plano. Em seguida, 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ê poderá desabilitar o JIT rápido usando essa propriedade MSBuild no arquivo de projeto:

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

para desabilitar completamente o TC, use essa propriedade MSBuild em seu arquivo de projeto:

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

Dica

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 obj os bin diretórios e e recompile).

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 aplicativos como o formato ReadyToRun (R2R). R2R é uma forma de compilação antecipada (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 à medida que seu aplicativo é carregado. Os binários contêm código nativo similar comparado ao que o JIT produziria. Entretanto, os binários R2R são maiores porque contêm código de IL (linguagem intermediária), 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 autocontido que tenha como alvo um RID (Runtime Environment) específico, como o Linux x64 ou o 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 autossuficiente. Por exemplo, esse comando cria um aplicativo autossuficiente para a versão de 64 bits do Windows:

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

Restrições de plataforma cruzada/arquitetura

O compilador ReadyToRun atualmente não tem suporte para o direcionamento cruzado. Você precisa compilar em determinado destino. Por exemplo, se você quiser imagens R2R para Windows x64, será necessário executar o comando Publicar nesse ambiente.

Exceções ao direcionamento cruzado:

  • 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.
  • O Linux x64 pode ser usado para compilar imagens do Linux ARM32 e ARM64.

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

Tempo de execução/SDK

Roll forward de tempo de execução de versão principal

O .NET Core 3.0 introduz um recurso opcional que permite que seu aplicativo efetue roll forward para a versão principal mais recente do .NET Core. Adicionalmente, foi adicionada uma nova configuração 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 runtime: rollForward
  • Variável de ambiente: DOTNET_ROLL_FORWARD
  • Argumento de linha de comando: --roll-forward

Um dos valores a seguir precisa ser especificado. Se a configuração for omitida, Secundária será o padrão.

  • LatestPatch
    Efetuar roll forward para a versão de patch mais recente. Isso desabilita o roll forward da versão secundária.
  • Secundária
    Se a versão secundária solicitada estiver ausente, efetue roll forward para a menor versão secundária mais alta. Se a versão secundária solicitada estiver presente, a política LatestPatch será usada.
  • Primária
    Se a versão principal solicitada estiver ausente, efetuar roll forward para a versão principal mais alta e a versão secundária mais baixa. Se a versão principal solicitada está presente, a política Secundária é usada.
  • LatestMinor
    Efetuar roll forward para a versão secundária mais recente, mesmo se a versão secundária solicitada estiver presente. Destinado a cenários de hospedagem de componente.
  • LatestMajor
    Efetuar roll forward para a versão principal e a secundária mais altas, mesmo se a principal solicitada estiver presente. Destinado a cenários de hospedagem de componente.
  • Desativar
    Não efetuar roll forward. Associar somente à versão especificada. Essa política não é recomendada para uso geral, pois ela desabilita a capacidade de efetuar roll forward para os patches mais recentes. Esse valor só é recomendado para teste.

Com a exceção da configuração Desabilitar, todas as configurações usarão a versão de patch mais recente disponível.

Por padrão, se a versão solicitada (conforme especificado em .runtimeconfig.json para o 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 nenhuma versão de lançamento correspondente, as versões de pré-lançamento serão levadas em conta. Esse comportamento pode ser alterado por meio da configuração DOTNET_ROLL_FORWARD_TO_PRERELEASE=1 , caso em que todas as versões são sempre consideradas.

O build copia dependências

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

Há algumas operações, como corte e publicação de página do Razor, 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 são associadas a um local específico no disco. Ferramentas locais não estão disponíveis globalmente e são distribuídas como pacotes NuGet.

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

Para ferramentas globais e locais, é necessária uma versão compatível do runtime. Muitas ferramentas que estão atualmente em NuGet.org direcionam para o runtime do .NET Core 2.1. Para instalar essas ferramentas, de forma global ou local, você ainda precisará instalar o Runtime do NET Core 2.1.

Novas opções 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 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 com suporte e novas regras de correspondência, consulte visão geral global. JSON.

Tamanhos menores de heap de coleta de lixo

O tamanho do heap do coletor de lixo padrão foi reduzido, resultando em menor uso de memória pelo .NET Core. Essa alteração se alinha melhor com o orçamento de alocação de geração 0 com os tamanhos de cache de processadores modernos.

Suporte de página grande de coleta de lixo

Páginas grandes (também conhecidas como páginas enormes no Linux) é um recurso em que o sistema operacional é capaz de estabelecer regiões de memória maiores do que o tamanho da página nativo (geralmente 4K) para melhorar o desempenho do aplicativo que está solicitando essas páginas grandes.

O coletor de lixo agora pode ser configurado com a configuração GCLargePages como um recurso opcional a ser escolhido para alocar páginas grandes no Windows.

& de área de trabalho Windows COM

Windows Installer do SDK do .NET Core

O instalador MSI para Windows foi alterado do .NET Core 3.0 em diante. Os instaladores de SDK agora atualizarão versões de faixa de recurso do SDK no local. Faixas de recurso são definidas nos grupos de centenas na seção patch do número de versão. Por exemplo, 3.0.101 e 3.0.201 são versões em duas faixas de recurso diferentes, enquanto 3.0.101 e 3.0.199 estão na mesma faixa de recurso. Além disso, quando o SDK do .NET Core 3.0.101 for instalado, o SDK do .NET Core 3.0.100 será removido do computador se ele existir. Quando o SDK do .NET Core 3.0.200 for instalado no mesmo computador, o SDK do .NET Core 3.0.101 não será removido.

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

Área de trabalho do Windows

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

O componente Windows Desktop faz parte do SDK do .NET Core 3.0 do Windows.

É possível criar um novo aplicativo de WPF ou Windows Forms com os seguintes comandos dotnet:

dotnet new wpf
dotnet new winforms

O Visual Studio 2019 adiciona modelos de Novo Projeto ao Windows Forms e WPF no .NET Core 3.0.

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

WinForms com DPI alto

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

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

  • DpiUnaware
  • SystemAware
  • PerMonitor
  • PerMonitorV2
  • DpiUnawareGdiScaled

Para obter mais informações sobre os modos de DPI alto, confira Desenvolvimento de aplicativos de área de trabalho de DPI alto no Windows.

Criar componentes COM

No Windows, agora você pode criar componentes gerenciados que podem ser chamados por COM. Essa funcionalidade é fundamental para usar o .NET Core com modelos de suplemento do COM e também para fornecer paridade com o .NET Framework.

Ao contrário do .NET Framework em que o mscoree. dll foi usado como o servidor COM, o .NET Core adicionará uma dll de inicializador nativa ao diretório bin quando você compilar o componente COM.

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

Interoperabilidade nativa do Windows

O Windows oferece uma API nativa rica na forma de APIs C simples, COM e WinRT. Embora o .NET Core dê suporte a P/Invoke, o .NET Core 3.0 adiciona a capacidade de criar conjuntamente APIs COM e ativar APIs 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 da área de trabalho do .NET Core 3.0 no Windows 10.

O Projeto de Empacotamento de Aplicativos do Windows, disponível no Visual Studio 2019, permite criar pacotes MSIX com aplicativos .NET Core autossuficientes.

O arquivo de projeto do .NET Core precisa especificar os runtimes compatíveis na propriedade <RuntimeIdentifiers>:

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

Aprimoramentos do Linux

SerialPort para Linux

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

Anteriormente, o .NET Core só dava suporte ao uso de SerialPort no Windows.

Para saber mais sobre o suporte limitado para a porta serial no Linux, confira o Problema do GitHub nº 33146.

Limites de memória do Docker e cgroup

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

  • Tamanho de heap do GC (coletor de lixo) padrão: 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 um percentual do limite de cgroup.
  • O tamanho mínimo do segmento reservado por heap de GC é de 16 MB. Esse tamanho reduz o número de heaps que são criados em computadores.

Suporte de GPIO para o Raspberry Pi

Foram lançados dois pacotes para o NuGet que você pode usar para programação de GPIO:

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

Suporte a ARM64 no Linux

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

Imagens do Docker para o .NET Core ARM64 estão disponíveis para Alpine, Debian e Ubuntu.

Observação

O suporte do Windows a ARM64 ainda não está disponível.

Segurança

TLS 1.3 e OpenSSL 1.1.1 no Linux

O .NET Core agora faz proveito do suporte a protocolo TLS 1.3 no OpenSSL 1.1.1 quando esse protocolo está disponível em um determinado ambiente. Com o TLS 1.3:

  • Tempos de conexão são aprimorados com um menor número de viagens de ida e volta necessárias entre o cliente e o servidor.
  • Segurança aprimorada devido à remoção de vários algoritmos criptográficos obsoletos e não seguros.

Quando disponíveis, o .NET Core 3.0 usa OpenSSL 1.1.1, 1.1.0 ou 1.0.2 em um sistema Linux. Quando o OpenSSL 1.1.1 está disponível, ambos os tipos System.Net.Security.SslStream e System.Net.Http.HttpClient usarão o protocolo TLS 1.3 (supondo que o cliente e o servidor deem suporte ao protocolo TLS 1.3).

Importante

Windows e macOS ainda não oferecem suporte a TLS 1.3.

O exemplo de 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 codificações AES-GCM e AES-CCM , implementadas com System.Security.Cryptography.AesGcm e System.Security.Cryptography.AesCcm respectivamente. Esses algoritmos são ambos do tipo AEAD (criptografia autenticada com os dados de associação).

O código a seguir demonstra como usar criptografia AesGcm 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.");
        }
    }
}

Importar/exportar chave de criptografia

O .NET Core 3.0 dá suporte à 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 principais, tais como RSA, DSA, ECDsa e ECDiffieHellman, dão suporte aos seguintes formatos:

  • Chave pública

    • X.509 SubjectPublicKeyInfo
  • Chave privada

    • PKCS nº 8 PrivateKeyInfo
    • PKCS nº 8 EncryptedPrivateKeyInfo

Chaves RSA também dão suporte a:

  • Chave pública

    • PKCS nº 1 RSAPublicKey
  • Chave privada

    • PKCS nº 1 RSAPrivateKey

Os métodos de exportação produzem dados binários codificados em DER e os métodos de importação esperam o mesmo. Se uma chave for armazenada no formato PEM compatível com texto, o chamador precisará decodificar o conteúdo em Base64 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));
        }
    }
}

Arquivos PKCS nº 8 podem ser inspecionados com System.Security.Cryptography.Pkcs.Pkcs8PrivateKeyInfo e arquivos PFX/PKCS nº 12 podem ser inspecionados com System.Security.Cryptography.Pkcs.Pkcs12Info. Arquivos PFX/PKCS nº 12 podem ser manipulados com System.Security.Cryptography.Pkcs.Pkcs12Builder.

Alterações da API do .NET Core 3,0

Intervalos e índices

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

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 tipo System.Range, que consiste em dois valores Index (um para o início e outro para o final) e pode ser escrito com uma expressão de intervalo x..y (C#). Em seguida, você pode indexar com um Range, o 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 tipo IAsyncEnumerable<T> é uma nova versão assíncrona de IEnumerable<T>. A linguagem permite o uso de await foreach em IAsyncEnumerable<T> para consumir seus elementos e o uso de yield return neles para produzir elementos.

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

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

Além de poder await foreach, você também pode criar iteradores assíncronos, por exemplo, um iterador que retorne um IAsyncEnumerable/IAsyncEnumerator em que é possível aplicar await e yield. Para objetos que precisam ser descartados, você pode usar IAsyncDisposable, que vários tipos BCL implementam, como Stream e Timer.

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

Ponto flutuante de IEEE

APIs de ponto flutuante estão sendo atualizadas para entrar 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 sejam compatíveis de forma comportamental com a especificação IEEE. Para obter mais informações sobre melhorias de ponto flutuante, consulte a postagem de ponto flutuante e aprimoramentos de formatação no blog do .NET Core 3,0 .

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

  • Analisar e arredondar corretamente entradas de qualquer tamanho.
  • Analisar e formatar corretamente o zero negativo.
  • Analisar corretamente Infinity e NaN, fazendo uma verificação sem diferenciação de maiúsculas e minúsculas e permitindo um + precedente opcional onde aplicável.

Novas APIs System.Math incluem:

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

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

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

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

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

  • FusedMultiplyAdd(Double, Double, Double)
    Corresponde à operação fma do IEEE; executa uma adição e multiplicação fundida. Em outras palavras, realiza (x * y) + z como uma única operação, minimizando o erro de arredondamento. Um exemplo é FusedMultiplyAdd(1e308, 2.0, -1e308) , que retorna 1e308 . O (1e308 * 2.0) - 1e308 regular retorna double.PositiveInfinity.

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

Intrínsecos dependentes da plataforma .NET

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

Quando apropriado, as bibliotecas .NET começaram usando estas instruções para melhorar o desempenho.

Para obter mais informações, consulte .NET Platform-Dependent Intrínsecos.

APIs de versão aprimoradas do .NET Core

Começando com o .NET Core 3.0, as APIs de versão fornecidas com o .NET Core agora retornam as informações que você espera. 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

Alteração da falha. Isso é tecnicamente uma alteração da falha, porque o esquema de controle de versão foi alterado.

Suporte interno rápido a JSON

Os usuários do .NET contaram amplamente com Newtonsoft.Json e outras bibliotecas JSON populares, que continuam sendo boas opções. Newtonsoft.Json usa cadeias de caracteres .NET como seu tipo de dados base, que é UTF-16 nos hoodes.

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 System.Text.Json o namespace e os tipos, consulte os seguintes artigos:

Suporte do HTTP/2

O tipo System.Net.Http.HttpClient dá suporte ao protocolo HTTP/2. Se o HTTP/2 estiver habilitado, a versão do protocolo HTTP é negociada via TLS/ALPN, e o HTTP/2 é usado apenas se o servidor selecionar seu uso.

O protocolo padrão permanece HTTP/1.1, mas o HTTP/2 pode ser ativado 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);

Segundo, você pode alterar 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, quando você está desenvolvendo um aplicativo, quer usar uma conexão não criptografada. Se você souber que o ponto de extremidade estará usando HTTP/2, poderá ativar conexões não criptografadas para HTTP/2. Você pode ativá-lo definindo a variável de ambiente DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2UNENCRYPTEDSUPPORT como 1 ou ativando-a no contexto do aplicativo:

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

Próximas etapas