safe(C# 參考)

safe情境關鍵字證明宣告在更新後的記憶體安全模型要求你明確做出安全選擇的地方是合理的。 你可以作為修改符應用 safe 於編譯器無法自行分類的宣告上,例如 extern 結構體中有明確佈局的成員或欄位。 safe修飾語是 的對應詞unsafesafe證明呼叫者不需要unsafe上下文,同時unsafe傳遞對呼叫者進行安全審核的義務。

Important

關鍵字safe是更新後記憶體安全模型的一部分,該模型是 C# 15 與 .NET 11 中的預覽功能。 編譯器接受 safe 成員及明確佈局欄位的修飾符 extern 。 不過,更新後的呼叫者安全規則尚未公開選擇,因此編譯器並未強制執行安全選擇 that(和 safeunsafe express):省略兩個修飾符不會產生錯誤,且兩個修飾符都不會改變呼叫者的行為。 要遵循此功能,請將編譯器選項設 LangVersionpreview。 完整設計請參見 記憶體安全功能規範

外部成員

成員 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)]的結構體中,欄位可能在記憶體中重疊,因此編譯器無法判斷讀取一個欄位是否合理。 你可以標記此類結構的每個欄位,或safeunsafe

// 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# 語法和使用方式的最終來源。

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

另請參閱