C# не станет Rust, но опасные участки придётся подсвечивать. Microsoft меняет правила для unsafe-кода

Низкоуровневый код снабдят «знаком опасности», чтобы он бросался в глаза ревьюерам.


bb9zdwdgmlmlb144622rtj3l99aza470.jpg

Microsoft готовит для C# крупное изменение в области безопасности памяти. Язык не собираются превращать в Rust и лишать привычного автоматического управления памятью, но работа с опасными участками кода станет заметнее, строже и понятнее для проверки.

О планах рассказал менеджер продукта .NET Ричард Ландер в большом тексте о будущем безопасности памяти в C# . Команда хочет, чтобы C# входил в число языков, которые выбирают не только за удобство разработки, но и за контроль типов и безопасности памяти. Главная часть замысла связана с новым смыслом ключевого слова unsafe, которое в C# разрешает использовать указатели и напрямую обращаться к памяти.

Большинство разработчиков бизнес-приложений почти никогда не пишет unsafe-код. В обычной разработке хватает управляемой памяти .NET и сборщика мусора, который сам следит за объектами и освобождает ресурсы. Но низкоуровневые задачи иногда требуют прямого доступа к памяти: взаимодействие с операционной системой, работа с памятью устройств, критичные по скорости участки программы или код, где нужны указатели.

В ранних книгах по C# unsafe описывали почти как вставку C-кода внутрь C#-программы. Такой режим разрешает использовать указатели и операции с ними, а сборщик мусора .NET не отслеживает память, на которую ссылаются указатели. Сейчас модификатор unsafe в основном открывает доступ к низкоуровневым возможностям, но сам по себе почти не влияет на тип или член класса.

В C# 16 поведение изменится. Версия должна выйти в конце 2027 года вместе с .NET 12, который получит статус LTS, то есть долгосрочной поддержки. Предварительная версия новой модели ожидается раньше, в C# 15 и .NET 11.

По текущему проекту спецификации , метод с пометкой unsafe будет одновременно требовать unsafe-контекст у вызывающего кода. Иначе говоря, опасная зона начнёт распространяться вверх по цепочке вызовов, пока разработчик явно не ограничит область внутри метода. Безопасный базовый метод также нельзя будет переопределить unsafe-версией, если исходный член класса не требует опасного контекста.

Отдельного модификатора safe пока не вводят, хотя часть разработчиков просит именно такую явную пометку для подавления распространения unsafe. Ландер признаёт , что сам поддерживает подобный вариант и обсуждает подход с командой проектирования языка.

Ещё одно важное изменение касается области действия unsafe. В будущем unsafe нельзя будет повесить на весь класс или структуру сразу. Разработчику придётся отмечать конкретные места, где код действительно работает с памятью напрямую: отдельные методы, свойства и поля. Так ревьюеры быстрее увидят участок, где программа выходит за рамки обычной модели безопасности.

Microsoft также пересматривает само понятие опасной операции. Использование типа указателя и некоторых выражений с указателями больше не будет автоматически считаться unsafe. Опасным признают момент, когда код разыменовывает указатель и получает доступ к неуправляемой памяти. Новый подход должен отделить само хранение адреса от реального чтения или записи в память.

В C# 16 новая модель безопасности будет добровольной. Разработчики смогут продолжать работу по старым правилам C# 1.0, но библиотеки среды выполнения .NET перейдут на новый режим. Microsoft также рассматривает значки в NuGet, репозитории пакетов для .NET, чтобы показывать, какие библиотеки уже включили новую модель, и подталкивать экосистему к переходу. В одной из будущих версий C# компания может сделать новый режим включённым по умолчанию.

Новая схема не делает unsafe-код безопасным магическим образом. Задача проще и практичнее: опасные участки должны бросаться в глаза, попадать в ревью и сопровождаться понятным контрактом использования. Разработчиков будут поощрять описывать правила работы с unsafe-членами в комментариях, а статические анализаторы смогут напоминать о документации и проверять соблюдение требований.

Реакция сообщества пока в основном спокойная и скорее положительная. Один из разработчиков, который пишет на C# и Rust, назвал изменения шагом к управляемому Rust: C# сохранит сборщик мусора и привычную модель .NET, но получит более строгие границы вокруг кода, способного напрямую трогать память.

Для авторов обычных корпоративных приложений переход почти ничего не поменяет. Большая часть таких проектов не использует unsafe и останется в привычной зоне C#. Но для библиотек, среды выполнения, системного кода и высокопроизводительных компонентов новая модель может стать заметным усилением: опасный код не исчезнет, зато перестанет прятаться внутри крупных классов и неочевидных вызовов.