Partilhar via


O que há de novo nas bibliotecas do .NET para .NET 10

Este artigo descreve novos recursos nas bibliotecas .NET para .NET 10. É atualizado para o Preview 5.

Criptografia

Localizar certificados por impressões digitais diferentes de SHA-1

Encontrar certificados exclusivamente por impressão digital é uma operação bastante comum, mas o X509Certificate2Collection.Find(X509FindType, Object, Boolean) método (para o FindByThumbprint modo) procura apenas o valor de impressão digital SHA-1.

Há algum risco em usar o Find método para encontrar impressões digitais SHA-2-256 ("SHA256") e SHA-3-256, uma vez que esses algoritmos de hash têm os mesmos comprimentos.

Em vez disso, o .NET 10 introduz um novo método que aceita o nome do algoritmo de hash a ser usado para correspondência.

X509Certificate2Collection coll = store.Certificates.FindByThumbprint(HashAlgorithmName.SHA256, thumbprint);
Debug.Assert(coll.Count < 2, "Collection has too many matches, has SHA-2 been broken?");
return coll.SingleOrDefault();

Encontre dados codificados em PEM em ASCII/UTF-8

A codificação PEM (originalmente Privacy Enhanced Mail, mas agora amplamente usada fora do e-mail) é definida para "texto", o que significa que a classe foi projetada para ser executada PemEncoding em String e ReadOnlySpan<char>. No entanto, é comum (especialmente no Linux) ter algo como um certificado escrito em um arquivo que usa a codificação ASCII (string). Historicamente, isso significava que você precisava abrir o arquivo e converter os bytes em caracteres (ou uma cadeia de caracteres) antes de poder usar PemEncodingo .

O novo PemEncoding.FindUtf8(ReadOnlySpan<Byte>) método aproveita o fato de que o PEM é definido apenas para caracteres ASCII de 7 bits e que o ASCII de 7 bits tem uma sobreposição perfeita com valores UTF-8 de byte único. Ao chamar esse novo método, você pode pular a conversão UTF-8/ASCII-to-char e ler o arquivo diretamente.

byte[] fileContents = File.ReadAllBytes(path);
-char[] text = Encoding.ASCII.GetString(fileContents);
-PemFields pemFields = PemEncoding.Find(text);
+PemFields pemFields = PemEncoding.FindUtf8(fileContents);

-byte[] contents = Base64.DecodeFromChars(text.AsSpan()[pemFields.Base64Data]);
+byte[] contents = Base64.DecodeFromUtf8(fileContents.AsSpan()[pemFields.Base64Data]);

Algoritmo de encriptação para exportação PKCS#12/PFX

Os novos métodos em ExportPkcs12 permitem que os chamadores escolham quais algoritmos de criptografia e digests são utilizados para gerar o resultado:

  • Pkcs12ExportPbeParameters.Pkcs12TripleDesSha1 indica o padrão de facto da era Windows XP. Ele produz uma saída suportada por quase todas as bibliotecas e plataformas que suportam a leitura de PKCS#12/PFX escolhendo um algoritmo de criptografia mais antigo.
  • Pkcs12ExportPbeParameters.Pbes2Aes256Sha256 indica que AES deve ser usado em vez de 3DES (e SHA-2-256 em vez de SHA-1), mas a saída pode não ser compreendida por todos os leitores (como o Windows XP).

Se quiseres ainda mais controlo, podes usar a sobrecarga que aceita um PbeParameters.

Criptografia pós-quântica (PQC)

O .NET 10 inclui suporte para três novos algoritmos assimétricos: ML-KEM (FIPS 203), ML-DSA (FIPS 204) e SLH-DSA (FIPS 205). Os novos tipos são:

  • System.Security.Cryptography.MLKem
  • System.Security.Cryptography.MLDsa
  • System.Security.Cryptography.SlhDsa

Como acrescenta pouco benefício, esses novos tipos não derivam de AsymmetricAlgorithm. Em vez da AsymmetricAlgorithm abordagem de criar um objeto e, em seguida, importar uma chave para ele, ou gerar uma nova chave, todos os novos tipos usam métodos estáticos para gerar ou importar uma chave:

using System;
using System.IO;
using System.Security.Cryptography;

private static bool ValidateMLDsaSignature(ReadOnlySpan<byte> data, ReadOnlySpan<byte> signature, string publicKeyPath)
{
    string publicKeyPem = File.ReadAllText(publicKeyPath);

    using (MLDsa key = MLDsa.ImportFromPem(publicKeyPem))
    {
        return key.VerifyData(data, signature);
    }
}

E em vez de definir propriedades de objeto e uma chave materializar-se, a geração de chaves nesses novos tipos incorpora todas as opções necessárias.

using (MLKem key = MLKem.GenerateKey(MLKemAlgorithm.MLKem768))
{
    string publicKeyPem = key.ExportSubjectPublicKeyInfoPem();
    ...
}

Todos esses algoritmos continuam com o padrão de ter uma propriedade estática IsSupported para indicar se o algoritmo é suportado no sistema atual.

Atualmente, os algoritmos PQC só estão disponíveis em sistemas onde as bibliotecas criptográficas do sistema são OpenSSL 3.5 (ou mais recentes). O suporte ao Windows CNG será adicionado em breve. Além disso, as novas classes são todas marcadas como [Experimental] no diagnóstico SYSLIB5006 até que o desenvolvimento seja concluído.

Globalização e data/hora

Novas sobrecargas de métodos em ISOWeek para o tipo DateOnly

A ISOWeek classe foi originalmente projetada para trabalhar exclusivamente com DateTime, pois foi introduzida antes do DateOnly tipo existir. Agora que DateOnly está disponível, faz sentido que ISOWeek também o suporte. As seguintes sobrecargas são novas:

Ordenação numérica para comparação de cadeias de caracteres

A comparação numérica de cadeias é um recurso altamente solicitado para comparar cadeias numericamente em vez de lexicograficamente. Por exemplo, 2 é menor que 10, por isso "2" deve aparecer antes "10" quando ordenado numericamente. Da mesma forma, "2" e "02" são iguais numericamente. Com a nova NumericOrdering opção, agora é possível fazer esses tipos de comparações:

StringComparer numericStringComparer = StringComparer.Create(CultureInfo.CurrentCulture, CompareOptions.NumericOrdering);

Console.WriteLine(numericStringComparer.Equals("02", "2"));
// Output: True

foreach (string os in new[] { "Windows 8", "Windows 10", "Windows 11" }.Order(numericStringComparer))
{
    Console.WriteLine(os);
}

// Output:
// Windows 8
// Windows 10
// Windows 11

HashSet<string> set = new HashSet<string>(numericStringComparer) { "007" };
Console.WriteLine(set.Contains("7"));
// Output: True

Esta opção não é válida para as seguintes operações de cadeia de caracteres baseadas em índice: IndexOf, LastIndexOf, StartsWith, EndsWithIsPrefix, e IsSuffix.

Nova TimeSpan.FromMilliseconds sobrecarga com parâmetro único

O TimeSpan.FromMilliseconds(Int64, Int64) método foi introduzido anteriormente sem adicionar uma sobrecarga que leva um único parâmetro.

Embora isso funcione como o segundo parâmetro é opcional, ele causa um erro de compilação quando usado em uma expressão LINQ como:

Expression<Action> a = () => TimeSpan.FromMilliseconds(1000);

O problema surge porque as expressões LINQ não podem lidar com parâmetros opcionais. Para resolver isso, o .NET 10 introduz uma nova sobrecarga que usa um único parâmetro. Altera igualmente o método existente para tornar obrigatório o segundo parâmetro.

Cordas

APIs de normalização de strings para trabalhar com intervalo de caracteres

A normalização de cadeia de caracteres Unicode tem sido suportada há muito tempo, mas as APIs existentes só funcionavam com o tipo de cadeia de caracteres. Isso significa que os chamadores com dados armazenados em diferentes formas, como matrizes de caracteres ou vãos, devem alocar uma nova cadeia de caracteres para usar essas APIs. Além disso, as APIs que retornam uma cadeia de caracteres normalizada sempre alocam uma nova cadeia de caracteres para representar a saída normalizada.

O .NET 10 apresenta novas APIs que funcionam com extensões de caracteres, que expandem a normalização além dos tipos de cadeia de caracteres e ajudam a evitar alocações desnecessárias:

Coleções

Adicionais TryAdd e TryGetValue sobrecargas para OrderedDictionary<TKey, TValue>

OrderedDictionary<TKey,TValue> fornece TryAdd e TryGetValue para adição e recuperação como qualquer outra IDictionary<TKey, TValue> implementação. No entanto, há cenários em que você pode querer executar mais operações, portanto, novas sobrecargas são adicionadas que retornam um índice para a entrada:

Este índice pode então ser usado com GetAt e SetAt para acesso rápido à entrada. Um exemplo de aplicação da nova sobrecarga TryAdd é o de adicionar ou atualizar um par chave-valor no dicionário ordenado.

// Try to add a new key with value 1.
if (!orderedDictionary.TryAdd(key, 1, out int index))
{
    // Key was present, so increment the existing value instead.
    int value = orderedDictionary.GetAt(index).Value;
    orderedDictionary.SetAt(index, value + 1);
}

Esta nova API já é usada em JsonObject e melhora o desempenho da atualização de propriedades em 10 a 20%.

Serialização

Permitir a especificação de ReferenceHandler em JsonSourceGenerationOptions

Quando você usa geradores de código-fonte para serialização JSON, o contexto gerado é gerado quando os ciclos são serializados ou desserializados. Agora você pode personalizar esse comportamento especificando o ReferenceHandler no JsonSourceGenerationOptionsAttribute. Aqui está um exemplo usando JsonKnownReferenceHandler.Preserve:

public static void MakeSelfRef()
{
    SelfReference selfRef = new SelfReference();
    selfRef.Me = selfRef;

    Console.WriteLine(JsonSerializer.Serialize(selfRef, ContextWithPreserveReference.Default.SelfReference));
    // Output: {"$id":"1","Me":{"$ref":"1"}}
}

[JsonSourceGenerationOptions(ReferenceHandler = JsonKnownReferenceHandler.Preserve)]
[JsonSerializable(typeof(SelfReference))]
internal partial class ContextWithPreserveReference : JsonSerializerContext
{
}

internal class SelfReference
{
    public SelfReference Me { get; set; } = null!;
}

System.Numerics

Mais métodos de transformação de matriz de esquerda

O .NET 10 adiciona as APIs restantes para criar matrizes de transformação canhotas para matrizes de billboard e constrained-billboard. Você pode usar esses métodos como seus homólogos destros existentes, por exemplo, CreateBillboard(Vector3, Vector3, Vector3, Vector3)ao usar um sistema de coordenadas canhoto:

Melhoramentos de tensores

A interface System.Numerics.Tensors agora inclui uma versão não genérica, IReadOnlyTensor, para operações como o acesso a Lengths e Strides. As operações de fatia não copiam mais dados, o que melhora o desempenho. Além disso, pode aceder a dados de forma não genérica, encaixotando para object quando o desempenho não é crítico.

Validação de opções

Novo construtor AOT-safe para ValidationContext

A ValidationContext classe, usada durante a validação de opções, inclui uma nova sobrecarga de construtor que aceita explicitamente o displayName parâmetro:

ValidationContext(Object, String, IServiceProvider, IDictionary<Object,Object>)

O nome de exibição garante a segurança da AOT e permite seu uso em compilações nativas sem avisos.

Diagnóstico

Suporte para URLs de esquema de telemetria em ActivitySource e Meter

ActivitySource e Meter agora suporta a especificação de uma URL de esquema de telemetria durante a construção, que se alinha com as especificações do OpenTelemetry . O esquema de telemetria garante consistência e compatibilidade para dados de rastreamento e métricas. Além disso, o .NET 10 apresenta ActivitySourceOptions, que simplifica a criação de instâncias com várias opções de configuração (incluindo a URL do esquema de ActivitySource).

As novas APIs são:

A Activity classe permite o rastreamento distribuído rastreando o fluxo de operações entre serviços ou componentes. O .NET suporta a serialização desses dados de rastreamento fora do processo através do fornecedor de origem de eventos Microsoft-Diagnostics-DiagnosticSource. Um Activity pode incluir metadados adicionais, como ActivityLink e ActivityEvent. O .NET 10 adiciona suporte para serializar esses links e eventos, de modo que os dados de rastreamento fora de processo agora incluem essas informações. Por exemplo:

Events->"[(TestEvent1,​2025-03-27T23:34:10.6225721+00:00,​[E11:​EV1,​E12:​EV2]),​(TestEvent2,​2025-03-27T23:34:11.6276895+00:00,​[E21:​EV21,​E22:​EV22])]"
Links->"[(19b6e8ea216cb2ba36dd5d957e126d9f,​98f7abcb3418f217,​Recorded,​null,​false,​[alk1:​alv1,​alk2:​alv2]),​(2d409549aadfdbdf5d1892584a5f2ab2,​4f3526086a350f50,​None,​null,​false)]"

Suporte para amostragem de monitorização com limite de taxa

Quando os dados de rastreamento distribuídos são serializados fora de processo por meio do provedor de origem de eventos Microsoft-Diagnostics-DiagnosticSource, todas as atividades registradas podem ser emitidas ou a amostragem pode ser aplicada com base em uma proporção de rastreamento.

Uma nova opção de amostragem chamada Amostragem de Limitação de Taxa restringe o número de atividades raiz serializadas por segundo. Isso ajuda a controlar o volume de dados com mais precisão.

Os agregadores de dados de rastreamento fora do processo podem habilitar e configurar esta amostragem especificando a opção em FilterAndPayloadSpecs. Por exemplo, a configuração a seguir limita a serialização a 100 atividades raiz por segundo em todas as ActivitySource instâncias:

[AS]*/-ParentRateLimitingSampler(100)

Arquivos ZIP

Melhorias de desempenho e memória do ZipArchive

O .NET 10 melhora o desempenho e o uso de memória do ZipArchive.

Primeiro, a forma como as entradas são gravadas no ZipArchive quando está em modo Update foi otimizada. Anteriormente, todas as ZipArchiveEntry instâncias eram carregadas na memória e reescritas, o que poderia levar a altos gargalos de uso de memória e desempenho. A otimização reduz o uso de memória e melhora o desempenho, evitando a necessidade de carregar todas as entradas na memória.

Em segundo lugar, a extração de entradas agora é paralelizada e as estruturas de dados internas são otimizadas para um melhor uso da ZipArchive memória. Essas melhorias abordam problemas relacionados a gargalos de desempenho e alto uso de memória, tornando ZipArchive mais eficiente e rápido, especialmente ao lidar com arquivos grandes.

Novas APIs ZIP assíncronas

O .NET 10 introduz novas APIs assíncronas que facilitam a execução de operações sem bloqueio ao ler ou gravar em arquivos ZIP. Este recurso foi muito solicitado pela comunidade.

Novos async métodos estão disponíveis para extrair, criar e atualizar arquivos ZIP. Esses métodos permitem que os desenvolvedores lidem com arquivos grandes de forma eficiente e melhorem a capacidade de resposta do aplicativo, especialmente em cenários que envolvem operações vinculadas a E/S. Esses métodos incluem:

Para obter exemplos de como usar essas APIs, consulte a postagem do blog Preview 4.

Melhoria de desempenho no GZipStream para fluxos concatenados

Uma contribuição da comunidade melhorou o desempenho ao processar fluxos de GZipStream dados GZip concatenados. Anteriormente, cada novo segmento de fluxo descartava e realocava o interno ZLibStreamHandle, o que resultava em alocações de memória adicionais e sobrecarga de inicialização. Com essa alteração, o identificador agora é redefinido e reutilizado para reduzir as alocações de memória gerenciada e não gerenciada e melhorar o tempo de execução. O maior impacto (~35% mais rápido) é visto ao processar um grande número de pequenos fluxos de dados. Esta alteração:

  • Elimina a alocação repetida de ~64-80 bytes de memória por fluxo concatenado, com economia adicional de memória não gerenciada.
  • Reduz o tempo de execução em aproximadamente 400 ns por fluxo concatenado.