Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье описываются новые возможности библиотек .NET для .NET 10. Оно было обновлено для предварительной версии 6.
Криптография
- Поиск сертификатов по отпечаткам, отличным от SHA-1
- Найдите данные, закодированные в PEM, в кодировке ASCII/UTF-8
- Алгоритм шифрования для экспорта PKCS#12/PFX
- Постквантовая криптография (PQC)
Поиск сертификатов по отпечаткам, отличным от SHA-1
Поиск сертификатов однозначно по отпечатку является довольно распространенной операцией, но X509Certificate2Collection.Find(X509FindType, Object, Boolean) метод (для FindByThumbprint режима) ищет только значение отпечатка SHA-1.
Существует некоторый риск использования Find
метода для поиска SHA-2-256 (SHA256) и SHA-3-256 отпечатков, так как эти хэш-алгоритмы имеют ту же длину.
Вместо этого .NET 10 представляет новый метод , который принимает имя хэш-алгоритма для сопоставления.
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();
Поиск данных в кодировке PEM в ASCII/UTF-8
Кодировка PEM (первоначально Privacy Enhanced Mail, но в настоящее время широко используется за пределами электронной почты) определена для "текста", что означает, что PemEncoding класс был разработан для запуска String и ReadOnlySpan<char>
. Однако обычно (особенно в Linux) есть сертификат, написанный в файле, использующий кодировку ASCII (string). Исторически это означает, что необходимо открыть файл и преобразовать байты в chars (или строку), прежде чем можно было использовать PemEncoding
.
Новый PemEncoding.FindUtf8(ReadOnlySpan<Byte>) метод использует преимущество того факта, что PEM определен только для 7-разрядных символов ASCII, и что 7-разрядный ASCII имеет идеальное перекрытие с однобайтовым значением UTF-8. Вызвав этот новый метод, можно пропустить преобразование UTF-8/ASCII в char и прочитать файл напрямую.
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]);
Алгоритм шифрования для экспорта PKCS#12/PFX
Новые методы на ExportPkcs12 и X509Certificate позволяют вызывающим пользователям выбирать, какие алгоритмы шифрования и хэширования используются для создания выходных данных.
- Pkcs12ExportPbeParameters.Pkcs12TripleDesSha1 указывает, что стандарт Windows XP-эры де-факто является стандартным. Он создает выходные данные, поддерживаемые почти каждой библиотекой и платформой, которая поддерживает чтение PKCS#12/PFX, выбрав старый алгоритм шифрования.
- Pkcs12ExportPbeParameters.Pbes2Aes256Sha256 указывает, что AES следует использовать вместо 3DES (и SHA-2-256 вместо SHA-1), но выходные данные могут не пониматься всеми средствами чтения (например, Windows XP).
Если вы хотите еще больше управления, можно использовать перегрузку , которая принимает значение PbeParameters.
Постквантовая криптография (PQC)
.NET 10 включает поддержку трех новых асимметричных алгоритмов: ML-KEM (FIPS 203), ML-DSA (FIPS 204) и SLH-DSA (FIPS 205). Новые типы:
-
System.Security.Cryptography.MLKem
-
System.Security.Cryptography.MLDsa
-
System.Security.Cryptography.SlhDsa
Поскольку он добавляет мало преимуществ, эти новые типы не являются производными от AsymmetricAlgorithm.
AsymmetricAlgorithm
Вместо подхода к созданию объекта, а затем импорту ключа в него или созданию нового ключа все типы используют статические методы для создания или импорта ключа:
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);
}
}
Вместо того, чтобы задавать свойства объекта и материализовать ключ, генерация ключей на этих новых типах учитывает все необходимые варианты.
using (MLKem key = MLKem.GenerateKey(MLKemAlgorithm.MLKem768))
{
string publicKeyPem = key.ExportSubjectPublicKeyInfoPem();
...
}
Эти алгоритмы продолжают использовать шаблон статического IsSupported
свойства, чтобы указать, поддерживается ли алгоритм в текущей системе.
.NET 10 включает API шифрования Windows: поддержка следующего поколения (CNG) для шифрования Post-Quantum (PQC), что делает эти алгоритмы доступными в системах Windows с поддержкой PQC. Рассмотрим пример.
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);
}
Алгоритмы PQC доступны в системах, где системные криптографические библиотеки — OpenSSL 3.5 (или более поздней версии) или Windows CNG с поддержкой PQC. Кроме того, новые классы помечены как [Experimental]
в разделе диагностики SYSLIB5006
до завершения разработки.
Глобализация и дата/время
- Новые перегрузки методов в ISOWeek для типа DateOnly
- Числовое упорядочение для сравнения строк
-
Новая
TimeSpan.FromMilliseconds
перегрузка с одним параметром
Новые перегрузки методов в ISOWeek для типа DateOnly
Класс ISOWeek изначально был разработан для работы исключительно с DateTime, так как он был введен до того, как тип DateOnly существовал. Теперь, когда DateOnly
доступен, имеет смысл, чтобы ISOWeek
также поддерживал его. Следующие перегрузки являются новыми:
Числовое упорядочение для сравнения строк
Сравнение числовых строк — это высоко запрошенная функция для сравнения строк числовым образом, а не лексографически. Например, 2
меньше 10
, поэтому "2"
следует отображаться раньше "10"
при упорядочении числовых значений. Аналогично, "2"
и "02"
численно равны. С новым NumericOrdering вариантом теперь можно выполнить следующие типы сравнений:
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
Этот параметр недействителен для следующих строковых операций на основе индекса: IndexOf
, , LastIndexOf
StartsWith
, EndsWith
и IsPrefix
IsSuffix
.
Новая TimeSpan.FromMilliseconds
перегрузка с одним параметром
Метод TimeSpan.FromMilliseconds(Int64, Int64) был введен ранее без добавления перегрузки, которая принимает один параметр.
Хотя это работает, так как второй параметр является необязательным, он вызывает ошибку компиляции при использовании в выражении LINQ, например:
Expression<Action> a = () => TimeSpan.FromMilliseconds(1000);
Проблема возникает, так как выражения LINQ не могут обрабатывать необязательные параметры. Для решения этой проблемы .NET 10 представляет новую перегрузку , которая принимает один параметр. Он также изменяет существующий метод , чтобы сделать второй параметр обязательным.
Строки
API нормализации строк для работы с диапазоном символов
Нормализация строк Юникода поддерживается в течение длительного времени, но существующие API работали только с типом строки. Это означает, что вызывающие стороны с данными, хранящимися в разных формах, таких как массивы символов или интервалы, должны выделить новую строку для использования этих API-интерфейсов. Кроме того, API, возвращающие нормализованную строку, всегда выделяют новую строку для представления нормализованных выходных данных.
.NET 10 представляет новые API, которые работают с диапазонами символов, которые расширяют нормализацию за пределами строковых типов и помогают избежать ненужных выделений:
- StringNormalizationExtensions.GetNormalizedLength(ReadOnlySpan<Char>, NormalizationForm)
- StringNormalizationExtensions.IsNormalized(ReadOnlySpan<Char>, NormalizationForm)
- StringNormalizationExtensions.TryNormalize(ReadOnlySpan<Char>, Span<Char>, Int32, NormalizationForm)
Коллекции
Дополнительные TryAdd
и TryGetValue
перегрузки для OrderedDictionary<TKey, TValue>
OrderedDictionary<TKey,TValue> предоставляет TryAdd
и TryGetValue
для добавления и извлечения, как и для любой другой IDictionary<TKey, TValue>
реализации. Однако существуют сценарии, в которых может потребоваться выполнить больше операций, поэтому добавляются новые перегрузки, которые возвращают индекс к записи.
Затем этот индекс можно использовать с GetAt и SetAt для быстрого доступа к записи. Пример использования новой TryAdd
перегрузки заключается в добавлении или обновлении пары "ключ-значение" в упорядоченном словаре:
// 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);
}
Этот новый API уже используется JsonObject и повышает производительность обновления свойств на 10–20%.
Сериализация
-
Разрешить указать ReferenceHandler в
JsonSourceGenerationOptions
- Параметр запретить повторяющиеся свойства JSON
- Строгие параметры сериализации JSON
Разрешить указание ReferenceHandler в JsonSourceGenerationOptions
При использовании генераторов источников для сериализации JSON созданный контекст вызывается при сериализации или десериализации циклов. Теперь вы можете настроить это поведение, указав ReferenceHandler в JsonSourceGenerationOptionsAttribute. Ниже приведен пример использования 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!;
}
Параметр запретить повторяющиеся свойства JSON
Спецификация JSON не указывает, как обрабатывать повторяющиеся свойства при десериализации полезных данных JSON. Это может привести к непредвиденным результатам и уязвимостям системы безопасности. В .NET 10 представлен JsonSerializerOptions.AllowDuplicateProperties параметр, который запрещает повторение свойств JSON:
string json = """{ "Value": 1, "Value": -1 }""";
Console.WriteLine(JsonSerializer.Deserialize<MyRecord>(json).Value); // -1
JsonSerializerOptions options = new() { AllowDuplicateProperties = false };
JsonSerializer.Deserialize<MyRecord>(json, options); // throws JsonException
JsonSerializer.Deserialize<JsonObject>(json, options); // throws JsonException
JsonSerializer.Deserialize<Dictionary<string, int>>(json, options); // throws JsonException
JsonDocumentOptions docOptions = new() { AllowDuplicateProperties = false };
JsonDocument.Parse(json, docOptions); // throws JsonException
record MyRecord(int Value);
Дубликаты обнаруживаются путем проверки того, назначено ли значение несколько раз во время десериализации, поэтому это функционирует как следует с другими параметрами, такими как чувствительность к регистру и политика именования.
Строгие параметры сериализации JSON
Сериализатор JSON принимает множество параметров для настройки сериализации и десериализации, но значения по умолчанию могут быть слишком расслаблены для некоторых приложений. .NET 10 добавляет новую JsonSerializerOptions.Strict предустановку, которая соответствует рекомендациям, включая следующие варианты:
- Применяет политику JsonUnmappedMemberHandling.Disallow.
- Отключает JsonSerializerOptions.AllowDuplicateProperties.
- Сохраняет привязку конфиденциальных свойств регистра.
- Включает настройки как JsonSerializerOptions.RespectNullableAnnotations, так и JsonSerializerOptions.RespectRequiredConstructorParameters.
Эти параметры совместимы с JsonSerializerOptions.Default — объект, сериализованный с помощью JsonSerializerOptions.Default, можно десериализовать с помощью JsonSerializerOptions.Strict.
Дополнительные сведения о сериализации JSON см. в обзоре System.Text.Json.
System.Numerics
Дополнительные методы преобразования матрицы с левой рукой
.NET 10 добавляет оставшиеся API для создания левоориентированных матриц преобразования для билбордов и ограниченных билборд-матриц. Эти методы можно использовать аналогично их существующим правосторонним аналогам, например CreateBillboard(Vector3, Vector3, Vector3, Vector3), когда вместо этого используется левосторонняя система координат.
- Matrix4x4.CreateBillboardLeftHanded(Vector3, Vector3, Vector3, Vector3)
- Matrix4x4.CreateConstrainedBillboardLeftHanded(Vector3, Vector3, Vector3, Vector3, Vector3)
Усовершенствования Tensor
Теперь интерфейс System.Numerics.Tensors включает негенерический интерфейс IReadOnlyTensor для операций, таких как доступ к Lengths и Strides. Операции среза больше не копируют данные, что повышает производительность. Кроме того, вы можете получить доступ к данным без использования обобщений, упаковывая их в object
, если скорость работы не является критически важной.
Проверка параметров
Новый конструктор AOT-safe для ValidationContext
Класс ValidationContext, используемый во время проверки параметров, включает новую перегрузку конструктора, которая однозначно принимает параметр displayName
.
ValidationContext(Object, String, IServiceProvider, IDictionary<Object,Object>)
Отображаемое имя гарантирует безопасность AOT и позволяет использовать его в собственных сборках без предупреждений.
Диагностика
-
Поддержка URL-адресов схемы телеметрии в
ActivitySource
иMeter
- Поддержка трассировки вне proc для событий и ссылок активности
- Поддержка выборочного трассирования с ограничением скорости
Поддержка URL-адресов схемы телеметрии в ActivitySource
и Meter
ActivitySource и Meter теперь поддерживает указание URL-адреса схемы телеметрии во время построения, которая соответствует спецификациям OpenTelemetry. Схема телеметрии обеспечивает согласованность и совместимость данных трассировки и метрик. Кроме того, в .NET 10 представлено ActivitySourceOptions, что упрощает создание экземпляров ActivitySource с несколькими параметрами конфигурации (включая URL схемы телеметрии).
Новые API:
- ActivitySource(ActivitySourceOptions)
- ActivitySource.TelemetrySchemaUrl
- Meter.TelemetrySchemaUrl
- ActivitySourceOptions
Поддержка трассировки вне процесса для событий и ссылок активности
Класс Activity обеспечивает распределенную трассировку, отслеживая ход операций между службами и компонентами. .NET поддерживает сериализацию этих данных трассировки вне процесса с использованием поставщика событий Microsoft-Diagnostics-DiagnosticSource
. Объект Activity
может включать дополнительные метаданные, такие как ActivityLink и ActivityEvent. .NET 10 добавляет поддержку сериализации этих ссылок и событий, поэтому данные трассировки вне proc теперь включают эти сведения. Рассмотрим пример.
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)]"
Поддержка трассировки с лимитированием частоты
Если данные распределенной трассировки сериализуются вне процесса через Microsoft-Diagnostics-DiagnosticSource
поставщика источника событий, все записанные активности могут быть переданы или на основе соотношения трассировки может быть применена выборка.
Новый параметр выборки с именем "Ограничение скорости выборки" ограничивает количество сериализованных корневых действий в секунду. Это помогает более точно управлять объемом данных.
Агрегаторы данных трассировки вне proc могут включить и настроить эту выборку, указав параметр в FilterAndPayloadSpecs
. Например, следующий параметр ограничивает сериализацию до 100 корневых действий в секунду во всех ActivitySource
экземплярах:
[AS]*/-ParentRateLimitingSampler(100)
ZIP-файлы
- Улучшения производительности и памяти ZipArchive
- Новые асинхронные API ZIP
- Повышение производительности в GZipStream для объединенных потоков
Улучшения производительности и памяти ZipArchive
.NET 10 повышает производительность и использование ZipArchiveпамяти.
Во-первых, способ записи записей в ZipArchive
, находясь в режиме Update
, был оптимизирован. Ранее все ZipArchiveEntry экземпляры загружались в память и перезаписывались, что могло привести к высокому использованию памяти и узким местам в производительности. Оптимизация сокращает использование памяти и повышает производительность, избегая загрузки всех записей в память.
Во-вторых, извлечение ZipArchive записей теперь параллелизировано, а внутренние структуры данных оптимизированы для улучшения использования памяти. Эти улучшения устраняют проблемы, связанные с узкими местами производительности и большим объемом памяти, что делает ZipArchive
более эффективным и быстрым, особенно при работе с большими архивами.
Новые асинхронные API ZIP
.NET 10 представляет новые асинхронные API, которые упрощают выполнение неблокирующих операций при чтении или записи в ZIP-файлы. Эта функция была очень запрошена сообществом.
Новые async
методы доступны для извлечения, создания и обновления ZIP-архивов. Эти методы позволяют разработчикам эффективно обрабатывать большие файлы и улучшать скорость реагирования приложений, особенно в сценариях, связанных с операциями ввода-вывода. К этим методам относятся:
- ZipArchive.CreateAsync(Stream, ZipArchiveMode, Boolean, Encoding, CancellationToken)
- ZipArchiveEntry.OpenAsync(CancellationToken)
- ZipFile.CreateFromDirectoryAsync
- ZipFile.ExtractToDirectoryAsync
- ZipFile.OpenAsync
- ZipFile.OpenReadAsync(String, CancellationToken)
- ZipFileExtensions.CreateEntryFromFileAsync
- ZipFileExtensions.ExtractToDirectoryAsync
- ZipFileExtensions.ExtractToFileAsync
Примеры использования этих API см. в записи блога preview 4.
Повышение производительности в GZipStream для объединенных потоков
Вклад сообщества улучшил производительность GZipStream при обработке объединенных потоков данных GZip. Ранее каждый новый сегмент потока удалял и перераспределял внутренний ZLibStreamHandle
, что приводило к дополнительным выделениям памяти и накладным расходам на инициализацию. При этом изменении дескриптор теперь сбрасывается и используется повторно, чтобы уменьшить объем выделяемой управляемой и неуправляемой памяти и сократить время выполнения. Наибольший эффект (~35% быстрее) существенно проявляется при обработке большого количества небольших потоков данных. Это изменение:
- Устраняет повторное выделение около 64–80 байт памяти на каждый объединенный поток, дополнительно экономя неуправляемую память.
- Сокращает время выполнения примерно на 400 ns на объединенный поток.