.NET 8 уже в пути! Откройте для себя его новые возможности
Вы можете в это поверить? Такое ощущение, что только вчера мы были в восторге от .NET 7, и вот мы уже говорим о .NET 8!
Но не бойтесь, Microsoft усердно работает над тем, чтобы предоставить нам новейшие и замечательные функции, которые мы рассмотрим в этой статье.
Так что сядьте поудобнее, расслабьтесь и давайте погрузимся во все новые захватывающие обновления, которые приготовили для нас в .NET 8.
dotnet publish и dotnet pack
Microsoft выпустили потрясающую новую функцию для команд dotnet publish
и dotnet pack
, которая ещё больше упрощает создание готового к работе кода.
До этого обновления эти команды по умолчанию создавали Debug
ресурсы, что могло бы вызвать некоторые затруднения, если бы вы хотели создать готовый к работе код. Но теперь, с новым обновлением, dotnet publish
и dotnet pack
по умолчанию создают Release
ресурсы, что означает, что вы можете легко создавать готовый к работе код без каких-либо дополнительных шагов.
Но не волнуйтесь, если вам по какой-либо причине всё ещё нужно создать Debug ресурсы
. Это всё ещё возможно сделать, установив свойство PublishRelease
в значение false
.
Как работают dotnet publish и dotnet pack?
Сначала давайте создадим новое консольное приложение, используя команду dotnet new console
. Затем мы создадим проект с помощью dotnet build
и посмотрим на результат. В этом случае выходные данные будут находиться в режиме Debug
, поскольку это поведение dotnet build
по умолчанию.
Далее давайте запустим команду dotnet publish
для создания готового к работе кода. С новым обновлением эта команда будет создавать ресурсы Release
по умолчанию, что является именно тем, что нам нужно. Мы можем увидеть ресурсы Release
в каталоге /app/bin/Release/net8.0
.
Наконец, предположим, что по какой-то причине нам нужно создать Debug
ресурсы. Мы можем сделать это, снова запустив команду dotnet publish
, но на этот раз мы установим свойству PublishRelease
значение false
.
И это всё! Благодаря этой новой функции теперь проще, чем когда-либо, создавать готовый к работе код с помощью команд dotnet publish
и dotnet pack
.
📚Ознакомьтесь: dotnet publish and dotnet pack
Улучшения в сериализации System.Text.Json
System.Text.Json – это встроенная .NET Библиотека, предоставляющая функциональность сериализации и десериализации JSON. Она позволяет разработчикам конвертировать .NET объекты, преобразуя их в данные JSON и наоборот.
Теперь функционалы сериализации и десериализации System.Text.Json были улучшена для .NET 8.
Другой ряд улучшений, включённых в этот предварительный просмотр, содержится в генераторе исходных текстов при использовании с ASP.NET Ядра в собственных приложениях AOT, что делает их более надёжными и быстрыми.
Кроме того, генератор исходного кода будет поддерживать в .NET 8 сериализующие типы со свойствами required
и init
, которые уже поддерживались в сериализации на основе отражения.
Более того, теперь возможна настройка сериализации для элементов, которых нет в полезных данных JSON.
Наконец, свойства из иерархий интерфейсов теперь могут быть сериализованы, включая свойства как непосредственно реализованного интерфейса, так и его базового интерфейса. Давайте посмотрим на этот пример:
IDerived value = new DerivedImplement { Base = 0, Derived =1 };
JsonSerializer.Serialize(value); // {"Base":0,"Derived":1}
public interface IBase
{
public int Base { get; set; }
}
public interface IDerived : IBase
{
public int Derived { get; set; }
}
public class DerivedImplement : IDerived
{
public int Base { get; set; }
public int Derived { get; set; }
}
Теперь JsonNamingPolicy
была расширена, чтобы включить политики именования для преобразований имён свойств snake_case
(с подчёркиванием) и kebab-case
(с дефисом). Эти новые политики можно использовать таким же образом, как и JsonNamingPolicy.CamelCase
.
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower };
JsonSerializer.Serialize(new { PropertyName = "value" }, options); // { "property_name" : "value" }
Метод JsonSerializerOptions.MakeReadOnly()
даёт вам явный контроль над тем, когда экземпляр JsonSerializerOptions
заморожен. Вы также можете проверить, доступен ли он только для чтения, с помощью свойства IsReadOnly
.
📚Ознакомьтесь: System.Text.Json serialization
GetItems<T>()
Метод GetItems<T>()
– это новая функция в .NET 8, которая позволяет случайным образом выбирать определённое количество элементов из заданного набора.
Она может быть полезно в играх, симуляциях и других приложениях, где требуется случайность. Этот метод доступен и в System.Random
, и в System.Security.Cryptography.RandomNumberGenerator
.
В этом примере у нас есть массив объектов City
, и мы используем метод GetItems<T>()
, чтобы случайным образом выбрать 3 города из массива:
private static ReadOnlySpan<City> s_allCities = new[]
{
new City("New York", "USA"),
new City("London", "UK"),
new City("Paris", "France"),
new City("Tokyo", "Japan"),
new City("Sydney", "Australia"),
};
...
City[] selectedCities = Random.Shared.GetItems(s_allCities, 3);
foreach (City city in selectedCities)
{
Console.WriteLine(city.Name + ", " + city.Country);
}
// Output:
// Paris, France
// Tokyo, Japan
// Sydney, Australia
Затем мы перебираем выбранные города и выводим их название и страну на консоль. Выходные данные будут отличаться каждый раз, когда мы запускаем программу, потому что города выбираются случайным образом.
📚Ознакомьтесь: GetItems<T>()
Shuffle<T>()
Метод Shuffle<T>()
– это ещё одна новая функция в .NET 8, которая позволяет рандомизировать порядок элементов в промежутке.
Это важно в случаях машинного обучения, когда вы хотите устранить смещение путём рандомизации порядка данных обучения.
Вот пример, который показывает, как использовать Shuffle<T>()
с массивом объектов YourType
:
YourType[] trainingData = LoadTrainingData();
Random.Shared.Shuffle(trainingData);
IDataView sourceData = mlContext.Data.LoadFromEnumerable(trainingData);
DataOperationsCatalog.TrainTestData split = mlContext.Data.TrainTestSplit(sourceData);
model = chain.Fit(split.TrainSet);
IDataView predictions = model.Transform(split.TestSet);
// ...
В этом примере мы загружаем некоторые обучающие данные в массив объектов YourType
и используем Random.Shared
для изменения порядка расположения элементов.
Затем мы загружаем перетасованные данные в объект IDataView
, разделяем данные на обучающий и тестовый наборы и используем перетасованные данные для обучения модели. Наконец, мы используем обученную модель для составления прогнозов на тестовом наборе.
📚Ознакомьтесь: Shuffle<T>()
Улучшения производительности
.NET 8 вводит несколько новых типов, которые направлены на повышение производительности приложений.
1) Пространство имён System.Collections.Frozen
включает в себя два типа коллекций: FrozenDictionary<TKey,TValue>
и FrozenSet<T>
. Эти типы не допускают никаких изменений ключей и значений после создания коллекции, что позволяет выполнять более быстрые операции чтения, такие как TryGetValue()
. Они особенно полезны для коллекций, которые заполняются при первом использовании, а затем сохраняются в течение всего срока службы:
private static readonly FrozenDictionary<string, bool> s_configurationData =
LoadConfigurationData().ToFrozenDictionary(optimizeForReads: true);
// ...
if (s_configurationData.TryGetValue(key, out bool setting) && setting)
{
Process();
}
2) Тип System.Text.CompositeFormat
полезен для оптимизации строк формата, которые неизвестны во время компиляции. На выполнение такой работы, как синтаксический анализ строки, затрачивается немного дополнительного времени, но это избавляет от необходимости выполнять работу при каждом использовании:
private static readonly CompositeFormat s_rangeMessage = CompositeFormat.Parse(LoadRangeMessageResource());
// ...
static string GetMessage(int min, int max) =>
string.Format(CultureInfo.InvariantCulture, s_rangeMessage, min, max);
3) Тип System.Buffers.IndexOfAnyValues<T>
предназначен для передачи методам, которые ищут первое вхождение любого значения в передаваемой коллекции. .NET 8 добавляет новые перегрузки методов, таких как String.IndexOfAny
и MemoryExtensions.IndexOfAny
, которые принимают экземпляр нового типа.
📚Ознакомьтесь: Performance-focused types
Собственный AOT
.NET 8 вносит улучшения в AOT, которая впервые была представлена в .NET 7. Публикация приложения в качестве встроенного AOT создаёт автономную версию приложения, для которой не требуется среда выполнения, поскольку всё включено в один файл.
В дополнение к существующей поддержке различных платформ, .NET 8 теперь включает поддержку архитектур x64 и Arm64 в macOS. Это означает, что разработчики теперь могут публиковать свои приложения .NET как собственный AOT для систем macOS.
Последние усовершенствования собственных приложений AOT в системах Linux привели к значительному сокращению размеров приложений.
Согласно недавним тестам, собственные приложения AOT, созданные с помощью .NET 8 Preview 1, теперь занимают на 50% меньше места по сравнению с приложениями, созданными с помощью .NET 7.
В строке ниже вы можете увидеть сравнение размера приложения “Hello World”, опубликованного с использованием native AOT и включающего всю среду выполнения .NET между двумя версиями:
Действующий System.NET 7.NET 8 Preview 1Linux x64 (с -p:StripSymbols=true)3.76 MB1.84 MBWindows x642.85 MB1.77 MB
Эти улучшения в native AOT могут помочь разработчикам .NET создавать меньшие по размеру, более быстрые и эффективные приложения, которые работают на различных платформах, не требуя каких-либо внешних зависимостей.
📚Ознакомьтесь: Native AOT
Генерация кода
.NET 8 также имеет некоторые улучшения в генерации кода и компиляции JIT (Just-In-Time), повышающие производительность и действенность:
- Улучшения производительности архитектуры Arm64
- Улучшения SIMD (Single Instruction Multiple Data) для лучшей векторизации и распараллеливания операций
- Встроенные в облако улучшения для повышения производительности в контейнерных средах
- Улучшения оптимизации, ориентированной на профиль (PGO), которые обеспечивают лучшую оптимизацию на основе шаблонов использования приложений
- Поддержка расширений AVX-512 ISA для более эффективных операций с плавающей запятой на современных процессорах
- Улучшения пропускной способности JIT (Just-In-Time) для более быстрой генерации кода
- Циклическая и общая оптимизация, повышающая производительность часто используемых блоков кода
Эти улучшения помогают разработчикам оптимизировать производительность своих приложений .NET и снизить использование ресурсов в облачных средах.
📚Ознакомьтесь: Code generation
Образы контейнеров .NET
.NET 8 также вносит несколько изменений в этот способ работы образов контейнера .NET. Во-первых, Debian 12 (Bookworm) теперь является дистрибутивом Linux по умолчанию в образах контейнеров.
Кроме того, образы включают non-root
пользователя, чтобы сделать их некорневыми. Чтобы запускаться от имени non-root
, добавьте строку USER app
в конце вашего файла Dockerfile или аналогичную инструкцию в ваших манифестах Kubernetes.
Порт по умолчанию также изменён с 80
на 8080
, и доступна новая переменная среды ASP NET CORE_HTTP_PORTS
, облегчающая смену портов.
Формат для переменной ASPNETCORE_HTTP_PORTS
проще по сравнению с форматом, требуемым ASPNETCORE_URLS
(он принимает список портов). Если вы измените порт обратно на 80
, используя одну из этих переменных, запуск от имени non-root
пользователя будет невозможен.
Чтобы загрузить .NET 8 Preview SDK, вы можете использовать следующий тег, который включает суффикс -preview
в название тега для образов контейнера предварительного просмотра:
docker run --rm -it mcr.microsoft.com/dotnet/sdk:8.0-preview
Суффикс -preview
больше не будет использоваться для выпусков-кандидатов (RC). Кроме того, разработчики могут использовать улучшенные образы Ubuntu с .NET 8, которые предлагают отсутствие менеджера пакетов или оболочки и возможность использования без root. Эти образы идеально подходят для разработчиков, которые ищут преимущества вычислений в стиле устройств.
📚Ознакомьтесь: .NET container images
Итак, вам не терпится опробовать эти новые функции в .NET 8? Как вы думаете, что будет наиболее полезным дополнением для ваших проектов? Не стесняйтесь загружать предварительный просмотр и изучать возможности. Удачи вам в ваших свершениях!