safe(C# 參考)

safe情境關鍵字標示宣告在更新後的記憶體安全模型下,不需使用地點的unsafe上下文。 修safe飾符是 的對應。unsafe 宣告者 safe 不需要不安全情境,但 unsafe 會向來電者傳遞安全審核義務。

使用 safe 關鍵字本身需要編 AllowUnsafeBlocks 譯器選項(-unsafe),即使呼叫者不需要上下文 unsafe 。 普通宣告預設是安全的,因此在不需要的地方省 safe 略,以避免不必要的不安全編譯。

Important

關鍵字safe是更新後記憶體安全模型的一部分,該模型是 C# 15 與 .NET 11 中的預覽功能。 設定 LangVersion 為 以 preview 啟用語法。 為了強制執行更新後的規則,包括明確 safe 的選擇或 unsafe 要求不安全的來電者義務,請啟用 updated-memory-safety-rules 編譯器功能。 關於啟用細節,請參見 啟用更新的記憶體安全規則。 完整設計請參見 記憶體安全功能規範。

允許且必須的聲明

你可以套用 safe 允許 requires-unsafe 修飾符的宣告,包括方法、建構子、屬性和欄位。 對於一般宣告,修飾符可以將預期的契約明確化,包括原始碼生成的程式碼。 這不僅限於 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 在不安全區塊上的區別,請參見 Unsafe context 要求。

外部成員

成員 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]的類型中,編譯器無法單獨分類每個實例欄位的安全性。 你要標記每個這樣的欄位,或unsafe是safe:

// 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.PackStructLayoutAttribute.Size的實例欄位套用相同的修飾符,包括序列和自動排版。 例如,序列版面類型 需要 Pack = 1 相同的明確選擇。 未指定或零值本身不會觸發額外規則。 靜態場和恆定場則不適用。 對於合成的背景欄位,將修飾符放在擁有的屬性或事件上。

關於 CS9392 訊息及其他合成儲存的修正,請參見 現場佈局安全。

C# 語言規格

如需詳細資訊,請參閱 C# 語言規格中的不安全程式碼。 語言規格是 C# 語法和使用方式的最終來源。

關於更新後記憶體安全模型的設計,請參閱 記憶體安全功能規範。

另請參閱