Каждый, кто хотя бы раз запускал Visual Studio, имел дело с файлом формата .sln. Это файл решения, который содержит информацию о структуре, конфигурации сборки, настройках платформы и других параметров. Но зачем спустя столько лет вводить новый формат .slnx и чем они друг от друга отличаются? Разберёмся в этой статье.

Формат .sln появился для упрощения управления проектами. Файл решения позволял группировать связанные проекты, что значительно упрощало процесс сборки и тестирования приложения.

С каждым обновлением Visual Studio формат .sln эволюционировал, чтобы поддерживать новые языки, например C# и Visual Basic, технологии, а также лучше интегрироваться с системами контроля версий.

Как было в старом .SLN

Несмотря на ряд преимуществ формата .sln, он также имеет множество недостатков:

  • слишком большой размер. При создании решения размер .sln-файла зачастую уже достаточно большой, и при добавлении проектов файл решения стремительно засоряется избыточными идентификаторами и метаданными;

  • бесполезные дубликаты. Большое количество дубликатов имён проектов и частей решения является рудиментом и не приносит пользы;

  • тяжело редактировать вручную. Из-за того, что формат ориентирован на использование инструментов, ручное редактирования файла решения зачастую приводит к ошибке;

  • нестандартный формат файла. Формат .sln является проприетарным, что ограничивает возможности совместимости и интеграции.

Давайте рассмотрим пример файла решения в формате .sln:

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31612.314
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Radzen.Blazor", 
"Radzen.Blazor\Radzen.Blazor.csproj", 
"{30919FA8-6A6A-45A3-9B05-0B65ABF8F70F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RadzenBlazorDemos", 
"RadzenBlazorDemos\RadzenBlazorDemos.csproj", 
"{DF9EC444-791A-415A-A3EB-C4B008E5FCB5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Radzen.Blazor.Tests", 
"Radzen.Blazor.Tests\Radzen.Blazor.Tests.csproj", 
"{BC20637F-A979-425A-9C3F-D72633FE555C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RadzenBlazorDemos.Host", 
"RadzenBlazorDemos.Host\RadzenBlazorDemos.Host.csproj", 
"{18702B3F-791E-45F3-BCFD-1792A1300AAB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RadzenBlazorDemos.Server", 
"RadzenBlazorDemos.Server\RadzenBlazorDemos.Server.csproj", 
"{EC869401-304A-45BC-93CA-C1CDFAAA7F7B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{30919FA8-6A6A-45A3-9B05-0B65ABF8F70F}.Debug|Any 
CPU.ActiveCfg = Debug|Any CPU
{30919FA8-6A6A-45A3-9B05-0B65ABF8F70F}.Debug|Any 
CPU.Build.0 = Debug|Any CPU
{30919FA8-6A6A-45A3-9B05-0B65ABF8F70F}.Release|Any 
CPU.ActiveCfg = Release|Any CPU
{30919FA8-6A6A-45A3-9B05-0B65ABF8F70F}.Release|Any 
CPU.Build.0 = Release|Any CPU
{DF9EC444-791A-415A-A3EB-C4B008E5FCB5}.Debug|Any 
CPU.ActiveCfg = Debug|Any CPU
{DF9EC444-791A-415A-A3EB-C4B008E5FCB5}.Debug|Any 
CPU.Build.0 = Debug|Any CPU
{DF9EC444-791A-415A-A3EB-C4B008E5FCB5}.Release|Any 
CPU.ActiveCfg = Release|Any CPU
{DF9EC444-791A-415A-A3EB-C4B008E5FCB5}.Release|Any 
CPU.Build.0 = Release|Any CPU
{BC20637F-A979-425A-9C3F-D72633FE555C}.Debug|Any 
CPU.ActiveCfg = Debug|Any CPU
{BC20637F-A979-425A-9C3F-D72633FE555C}.Debug|Any 
CPU.Build.0 = Debug|Any CPU
{BC20637F-A979-425A-9C3F-D72633FE555C}.Release|Any 
CPU.ActiveCfg = Release|Any CPU
{BC20637F-A979-425A-9C3F-D72633FE555C}.Release|Any 
CPU.Build.0 = Release|Any CPU
{18702B3F-791E-45F3-BCFD-1792A1300AAB}.Debug|Any 
CPU.ActiveCfg = Debug|Any CPU
{18702B3F-791E-45F3-BCFD-1792A1300AAB}.Debug|Any 
CPU.Build.0 = Debug|Any CPU
{18702B3F-791E-45F3-BCFD-1792A1300AAB}.Release|Any 
CPU.ActiveCfg = Release|Any CPU
{18702B3F-791E-45F3-BCFD-1792A1300AAB}.Release|Any 
CPU.Build.0 = Release|Any CPU
{EC869401-304A-45BC-93CA-C1CDFAAA7F7B}.Debug|Any 
CPU.ActiveCfg = Debug|Any CPU
{EC869401-304A-45BC-93CA-C1CDFAAA7F7B}.Debug|Any 
CPU.Build.0 = Debug|Any CPU
{EC869401-304A-45BC-93CA-C1CDFAAA7F7B}.Release|Any 
CPU.ActiveCfg = Release|Any CPU
{EC869401-304A-45BC-93CA-C1CDFAAA7F7B}.Release|Any 
CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BD0EF65D-06F5-4DBD-BF9F-82CA04E26D8C}
EndGlobalSection
EndGlobal

Сразу бросаются в глаза GUID`ы. Человеку уж очень неприятно читать и не хочется разбираться в таком файле. Также легко заметить, что файл уж очень громоздкий, и это при том, что я пытался подобрать наиболее скромного представителя формата .sln.

Изменения в новом .SLNX

В блоге Microsoft 13 марта 2025 года появилась статья, рассказывающая про новый формат решений .slnx (ссылка на статью). Однако официального релиза и документации пока нет.

Формат .slnx был представлен как новая версия формата .sln. Наиболее важным нововведением является использование формата XML, а также пробелов и комментариев. При создании .slnx разработчики задались целью сделать такой формат, который будет лаконичен, понятен и при этом сохранит все преимущества старого формата.

Преимущества формата .slnx перед .sln:

  • более понятный для человека. Новый формат разработан с учётом удобства для чтения и редактирования файла человеком;

  • использование формата XML. Переход к распространённому формату XML позволит новому формату решений стать более гибким в использовании;

  • уменьшение количества конфликтов слияния. Благодаря упрощению структуры файла снизилась вероятность возникновения конфликта слияния в системах контроля версий.

Пример файла решения в формате .slnx:

<Solution>
  <Project Path="Radzen.Blazor.Tests/Radzen.Blazor.Tests.csproj" />
  <Project Path="Radzen.Blazor/Radzen.Blazor.csproj" />
  <Project Path="RadzenBlazorDemos.Host/RadzenBlazorDemos.Host.csproj" />
  <Project Path="RadzenBlazorDemos.Server/RadzenBlazorDemos.Server.csproj" />
  <Project Path="RadzenBlazorDemos/RadzenBlazorDemos.csproj" />
</Solution>

И всё?! Да, это весь файл решения.

Для того, чтобы попробовать новый формат, необходимо сохранить решение в нём (логично). Сделать это можно в Visual Studio (File > Save Solution As) и выбрать в качестве расширения XML Solution File (*.slnx).

Также сохранить решение в новом формате можно в Rider. Для этого нужно нажать Save as > Save as XML Solution (.slnx).

Если по какой-то причине вы не хотите/не можете мигрировать на новый формат через IDE, то можете это сделать с помощью команды:

dotnet SLN <YourSolutionFile.SLN> migrate

Ограничения нового формата

Однако не спешите переводить все свои проекты на новый формат решений. Из-за того, что новый формат .slnx ещё слишком сырой, миграция в большинстве случаев откладывается.

Поскольку .slnx новый формат, многие сторонние инструменты, плагины и CI/CD системы работают только с .sln файлами. Также на текущем этапе не поддержаны некоторые функции, отсутствует подробная документация, а ещё могут возникнуть проблемы при работе с файлами разных форматов.

Однако уже сейчас MSBuild полностью поддерживает .slnx, обеспечивая бесшовную интеграцию с системами сборки .NET и C++. Также .NET CLI был обновлён, чтобы поддерживать новый формат. А ещё C# Dev Kit полностью поддерживает .slnx, облегчая работу с файлами решений в среде VS Code.

Новый формат всё ещё позиционируется как функция для предварительного просмотра и пока не был официально представлен. Но тем не менее сообщество программистов в целом позитивно относится к нововведению. Некоторые крупные проекты уже перешли на .slnx, например, файловый менеджер Files.

Подведём итоги

Новый формат .slnx является перспективным наследником старого проприетарного формата .sln. Но повальной миграции в ближайшее время не предвидится из-за того, что формат, по сути, ещё не успел официально выйти.

Однако основные инструменты вроде MSBuild и .NET CLI уже полностью поддерживают .slnx. Анализатор PVS-Studio с версии 7.37 также поддерживает анализ на основе нового формата решений. Но не пугайтесь, для пользователя запуск анализа никак не изменился: вам как всегда достаточно нажать одну кнопку в IDE.

Таким образом, уместно предположить, что к моменту официального выхода, .slnx будет поддерживать всё больше инструментов, поэтому в будущем число миграций будет расти.

Также приглашаю вас рассказать в комментариях, как вы относитесь к нововведению, или можете поделиться своей историей перехода к новому формату решений на ваших проектах.

Ну и по традициии: запросить новую версию анализатора PVS-Studio вы можете на нашем сайте :)

Комментарии (3)


  1. DjUmnik
    23.07.2025 12:32

    CMake еще не поддерживает