safe (C# 参考)

safe上下文关键字证明声明在更新的内存安全模型要求你明确做出安全选择的地方是健全的。 在编译器无法自行分类的声明上应用 safe 修饰符,例如 extern 具有显式布局或扩展布局的类型中的成员或字段。 safe修饰符是: unsafesafe证明调用方不需要unsafe上下文,同时unsafe向调用方传播审核安全的义务。

Important

关键字safe是更新的内存安全模型的一部分,它是 C# 15 和 .NET 11 中的预览功能。 preview设置为LangVersion启用语法。 若要强制实施更新的规则,包括显式 safe 或 unsafe 选择,并要求不安全的 updated-memory-safety-rules 调用方义务,请启用编译器功能。 有关激活详细信息,请参阅 “启用更新的内存安全规则”。 有关完整设计,请参阅 内存安全功能规范。

Extern 成员

成员 extern 调用本机代码,因此编译器无法对其安全性进行分类。 在更新的模型中,将标记每个extern声明,包括分LibraryImport部方法,或safeunsafe:

// 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 成员一样,启用更新的规则时省略这两个修饰符是一个错误。

C# 语言规范

有关详细信息,请参阅 C# 语言规范中的不安全代码。 语言规范是 C# 语法和用法的明确来源。

有关更新的内存安全模型的设计,请参阅 内存安全功能规范。

另见