safe (справочник по C#)

Контекстное safe ключевое слово помечает объявление как не требующее контекста unsafe на сайте использования в обновленной модели безопасности памяти. Модификатор safe является аналогом unsafe. Небезопасный контекст не требуется для вызывающих safe объявлений, в то время как unsafe распространяет обязательство проверять безопасность вызывающей стороны.

Для использования самого ключевого safe слова требуется AllowUnsafeBlocks параметр компилятора (-unsafe), даже если вызывающие пользователи не нуждаются в контексте unsafe . Обычные объявления являются безопасными по умолчанию, поэтому опущений safe , в которых не требуется, чтобы избежать ненужных операций, требующих небезопасной компиляции.

Important

Ключевое safe слово является частью обновленной модели безопасности памяти, предварительной версии функции в C# 15 и .NET 11. Установите для LangVersionpreview включения синтаксиса. Чтобы также применить обновленные правила, включая явные safe или unsafe небезопасные обязательства вызывающего абонента, включите функцию updated-memory-safety-rules компилятора. Дополнительные сведения о активации см. в разделе "Включить обновленные правила безопасности памяти". Полный дизайн см. в спецификации функции безопасности памяти.

Разрешенные и обязательные объявления

Можно применить safe к объявлениям, которые позволяют модификатору без безопасности, включая методы, конструкторы, свойства и поля. Для обычных объявлений модификатор может явным образом сделать предполагаемый контракт явным, в том числе в исходном коде. Он не ограничивается extern элементами и полями макета.

Для некоторых объявлений требуется явный выбор safe или unsafe включение обновленных правил. В следующих разделах описываются extern элементы и явные или расширенные поля макета.

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

В более новых компиляторах объявления также требуются, safe даже если вызывающие пользователи не нуждаются AllowUnsafeBlocksв небезопасном контексте. Задайте <AllowUnsafeBlocks>true</AllowUnsafeBlocks> в файле проекта разрешение CS9401. Эта проверка модификатора не зависит от применения обновленных правил. Roslyn документирует его, как было введено в Visual Studio 2026 версии 18.13, после .NET 11.0.100; компилятор .NET 11 RC2 не применяет это требование.safe Границы компилятора и различие от CS0227 в небезопасных блоках см. в разделе "Небезопасные требования к контексту".

Экстерн-члены

Член вызывает машинный extern код, поэтому компилятор не может классифицировать его безопасность. В обновленной модели помечается каждое extern объявление, включая частичный LibraryImport метод, safe либо unsafe:

// Syntax requires LangVersion preview; enforcement requires the updated-memory-safety-rules compiler feature.
[LibraryImport("libc")]
internal static safe partial int getpid();

[LibraryImport("libc", StringMarshalling = StringMarshalling.Utf8)]
internal static unsafe partial nint strlen(byte* str);

getpid не принимает параметров и возвращает примитив, поэтому автор подтверждает, что вызов является безопасным, и вызывающие используют его без контекста unsafe . strlen принимает необработанный указатель на то, что машинный код расшифровывается, поэтому объявление является unsafe и распространяет обязательство вызывающим его абонентам. При включении обновленных правил опущений оба модификатора являются ошибкой.

Явные или расширенные поля макета

В типе с [StructLayout(LayoutKind.Explicit)] или [ExtendedLayout], компилятор не может классифицировать безопасность каждого поля экземпляра самостоятельно. Помечаете каждое такое поле safe либо unsafe:

// Syntax requires LangVersion preview; enforcement requires the updated-memory-safety-rules compiler feature.
[StructLayout(LayoutKind.Explicit)]
internal struct Union
{
    [FieldOffset(0)]
    internal safe int AsInt;

    [FieldOffset(0)]
    internal safe float AsFloat;
}

Поле, которое содержит собственный указатель или тип которого в противном случае несет инвариантную систему типов, не может выразиться unsafe. Поле, тип которого полностью описан системой safeтипов. Это же правило применяется к полям явного макета и полям расширенного макета. Как и extern в случае с элементами, опущение обоих модификаторов является ошибкой при включении обновленных правил.

Примените те же модификаторы к полям экземпляров в типах с ненулевой StructLayoutAttribute.Pack или StructLayoutAttribute.Size, включая последовательный и автоматический макет. Например, для типа последовательного макета требуется Pack = 1 тот же явный выбор. Неопределенные или нулевые значения не активируют дополнительное правило самостоятельно. Статические и константные поля исключаются. Для синтезированных полей резервного копирования поместите модификатор в свойство или событие.

Сведения о сообщении CS9392 и исправлениях для другого синтезированного хранилища см. в разделе "Безопасность макета полей".

Спецификация языка C#

Дополнительные сведения см. в разделе " Небезопасный код " в спецификации языка C#. Спецификация языка является авторитетным источником синтаксиса и использования языка C#.

Сведения о проектировании обновленной модели безопасности памяти см. в спецификации функции безопасности памяти.

См. также