Novidades do .NET Core 3.0
Este artigo descreve as novidades do .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 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 versão agora no Windows, macOS ou Linux.
Para obter mais informações sobre a versão, consulte o comunicado do .NET Core 3.0.
O .NET Core 3.0 RC é considerado uma produção pronta pela Microsoft e tem suporte total. Se você estiver usando uma versão prévia, deverá passar para a versão RTM para dar suporte contínuo.
Aprimoramentos de linguagem C# 8.0
O C# 8.0 também faz parte dessa 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 recursos do C# 8.0, consulte Novidades do C# 8.0.
Tutoriais relacionados aos recursos de linguagem C# 8.0:
- Tutorial: Expressar sua intenção de design mais claramente com tipos de referência que permitem valor nulo e tipos que não permitem valor nulo
- Tutprial: Gerar e consumir fluxos assíncronos usando o C# 8.0 e .NET Core 3.0
- Tutorial: Usar padrões correspondentes para criar algoritmos controlados por tipo e controlados por dados
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 o .NET Standard 2.1. No entanto, o modelo dotnet new classlib
padrão gera um projeto que ainda tem como destino .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
, é criado um executável (conhecido como o appHost) 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.
appHost e notarização no macOS
Somente macOS
A partir do SDK 3.0 do .NET Core em cartório 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 Notarização do macOS Catalina 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 ele é executado do código-fonte com o comando dotnet run
ou iniciando o executável Mach-O diretamente.
Sem o appHost, a única maneira de um usuário iniciar um aplicativo dependente de estrutura é com o comando dotnet <filename.dll>
. Um appHost sempre é criado quando você publica seu aplicativo autocontido.
Você pode configurar o appHost no nível do projeto ou alternar o appHost para um comando dotnet
específico com o parâmetro -p:UseAppHost
:
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 configuração UseAppHost
, consulte Propriedades do 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.
O .NET Core agora inclui uma configuração que usará a ferramentaVinculador de IL para verificar a IL do seu aplicativo. Essa ferramenta detecta qual código é necessário e, em seguida, corta bibliotecas não usadas. 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 interrupção ocorre porque o cortador não tem ciência desse comportamento dinâmico e não pode determinar quais tipos de estrutura são necessários para reflexão. A ferramenta Cortador de IL pode ser configurada para estar ciente deste cenário.
Antes de mais nada, teste seu aplicativo depois de cortar.
Para saber mais sobre a ferramenta Cortador de IL, confira 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 runtime use de modo mais adaptável o compilador JIT (just-in-time) para conseguir um melhor desempenho.
O principal benefício da compilação em camadas é fornecer duas maneiras de jitting de métodos: em uma camada de baixa qualidade, mas mais rápida, ou em uma camada de maior qualidade, mas mais lenta. A qualidade refere-se ao quão bem o método é otimizado. O TC ajuda a aumentar o desempenho de um aplicativo quando ele passa por vários estágios da 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 é tendenciosa para o desempenho de estado estável em relação ao 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 um código compilado antecipadamente ou ReadyToRun, o código pré-gerado será usado.
- Caso contrário, o método será jitted. Normalmente, esses métodos são genéricos sobre tipos de valor.
- O JIT rápido produz o código de baixa qualidade (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 é preferencial durante a inicialização.
- O JIT de otimização completa produz código de maior qualidade (ou mais otimizado) mais lentamente. Para métodos em que o Quick JIT não seria usado (por exemplo, se o método for atribuído com MethodImplOptions.AggressiveOptimization), o JIT de otimização completa é usado.
Para métodos chamados com frequência, o compilador just-in-time eventualmente cria um 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 lento, 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 a TC, use esta configuração 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 um build limpo para que as novas configurações sejam refletidas (exclua os diretórios obj
e bin
e recompile).
Para obter mais informações sobre como configurar a compilação em tempo de execução, confira Opções de configuração do Runtime 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:
Adicione a configuração
<PublishReadyToRun>
ao seu projeto:<PropertyGroup> <PublishReadyToRun>true</PublishReadyToRun> </PropertyGroup>
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 execução.
Runtime/SDK
Roll forward de runtime 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. - Principal
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. - Desabilitar
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 versão, somente as versões de versão 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 versão correspondente, as versões de pré-lançamento serão levadas em conta. Esse comportamento pode ser alterado pela configuração DOTNET_ROLL_FORWARD_TO_PRERELEASE=1
, nesse caso, 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 exigem publicação.
Ferramentas locais
O .NET Core 3.0 apresenta ferramentas locais. Ferramentas locais são semelhantes às ferramentas globais, mas estã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 está ausente ou como uma diretiva para usar uma versão mais alta.
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 do 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.
Windows Desktop e 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 de 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 para os sistemas operacionais macOS Arm64 (ou "Apple Silicon") e Windows Arm64 foi adicionado posteriormente ao .NET 6.
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).
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 o suporte para as criptografias 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 na 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 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 estejam em conformidade comportamental com a especificação IEEE. Para obter mais informações sobre melhorias de ponto flutuante, consulte Melhorias de análise e formatação de ponto flutuante na postagem 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
eNaN
, 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çõesnextUp
enextDown
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)
retornadouble.Epsilon
.MaxMagnitude(Double, Double) e MinMagnitude(Double, Double)
Correspondem às operaçõesmaxNumMag
eminNumMag
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çãologB
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 quefloor(log2(x))
, mas feito com o mínimo de erro de arredondamento.ScaleB(Double, Int32)
Corresponde à operação IEEEscaleB
que usa um valor integral, ele retorna efetivamentex * pow(2, n)
, mas é feito com o mínimo de erro de arredondamento.Log2(Double)
Corresponde à operaçãolog2
do IEEE; retorna o logaritmo de base 2. Minimiza o erro de arredondamento.FusedMultiplyAdd(Double, Double, Double)
Corresponde à operaçãofma
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 retorna1e308
. O(1e308 * 2.0) - 1e308
regular retornadouble.PositiveInfinity
.CopySign(Double, Double)
Corresponde à operaçãocopySign
do IEEE; retorna o valor dex
, mas com o sinal dey
.
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 Intrínsecos dependentes da plataforma .NET.
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
Usuários do .NET têm dependido basicamente de Newtonsoft.Json e outras bibliotecas JSON populares, que continuam a ser boas opções. O Newtonsoft.Json
usa cadeias de caracteres do .NET como seu tipo de dados base, o qual subjacentemente é UTF-16.
O novo suporte JSON interno é de alto desempenho, baixa alocação e funciona com texto JSON codificado em UTF-8. Para obter mais informações sobre o namespace e os tipos System.Text.Json, consulte os seguintes artigos:
- Serialização do JSON no .NET - Visão geral
- Como serializar e desserializar JSON em .NET.
- Como migrar de Newtonsoft.Json para System.Text.Json
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);