safeコンテキスト キーワードは、更新されたメモリ安全モデルで安全性の選択を明示的にする必要がある場所で宣言が正しいことを証明します。
safeは、コンパイラが独自に分類できない宣言 (extern メンバーや、明示的なレイアウトを持つ構造体内のフィールドなど) に修飾子として適用します。
safe修飾子は、unsafeに対応します。safe呼び出し元はunsafeコンテキストを必要とせず、unsafeは呼び出し元に安全性を監査する義務を伝達することを証明します。
Important
safe キーワードは、更新されたメモリ 安全モデルの一部であり、C# 15 および .NET 11 のプレビュー機能です。 コンパイラは、extern メンバーと明示的なレイアウト フィールドの修飾子としてsafeを受け入れます。 ただし、更新された呼び出し元と安全の規則に対するパブリック オプトインはまだないため、コンパイラは、 safe と unsafe の明示的な安全性の選択を強制しません。両方の修飾子を省略してもエラーは発生せず、どちらの修飾子も呼び出し元が実行できる動作は変更されません。 この機能に従うために、 LangVersion コンパイラ オプションを preview に設定します。 完全な設計については、 メモリ安全機能の仕様を参照してください。
Extern メンバー
extern メンバーはネイティブ コードを呼び出すので、コンパイラはその安全性を分類できません。 更新されたモデルでは、externまたはLibraryImportのいずれかの部分メソッドsafe含め、すべてのunsafe宣言をマークします。
// Compiles under LangVersion preview, but the safety choice isn't enforced yet.
[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)]を持つ構造体では、フィールドがメモリ内で重複する可能性があるため、コンパイラは、1 つのフィールドを通した読み取りがサウンドであるかどうかを判断できません。 このような構造体のすべてのフィールドは、 safe または unsafeマークします。
// Compiles under LangVersion preview, but the safety choice isn't enforced yet.
[StructLayout(LayoutKind.Explicit)]
internal struct Union
{
[FieldOffset(0)]
internal safe int AsInt;
[FieldOffset(0)]
internal safe float AsFloat;
}
ネイティブ ポインターを保持するフィールド、または型システムが表現できない不変の型を持つフィールドは、 unsafe。 型システムによって完全に記述された型を持つフィールドが safe。
externメンバーと同様に、両方の修飾子を省略することは、更新されたモデルの下でエラーになることが意図されていますが、コンパイラはまだその規則を適用していません。
C# 言語仕様
詳細については、「C# 言語仕様の安全でないコード」を参照してください。 言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。
更新されたメモリ安全モデルの設計については、 メモリ安全機能の仕様を参照してください。
こちらも参照ください
.NET