解決不安全程式碼建構中的錯誤和警告

本文涵蓋以下編譯器診斷:

  • CS0193* 或 -> 運算子必須套用在指標上
  • CS0196指標只能由一個值編製索引
  • CS0208無法取得受管理類型('type')的位址、取得其大小或宣告指向其的指標
  • CS0209語句中 fixed 宣告的本地類型必須是指標型別
  • CS0210您必須在fixedusing陳述宣告中提供初始化器
  • CS0211無法取得指定運算式的位址
  • CS0212你只能在語句初始化器中 fixed 取得未固定表達式的位址
  • CS0213你不能用這個 fixed 陳述來取得已經固定的表達式的位址
  • CS0214指標和固定大小緩衝區只能在不安全的內容中使用
  • CS0227不安全程式碼僅可在使用/unsafe編譯時出現
  • CS0233:「 識別碼」沒有預先定義的大小,因此 sizeof 只能在不安全的內容中使用
  • CS0242此操作未定義於 void 指標上
  • CS0244'' 和 'isas' 在指標類型上都無效
  • CS0254固定陳述式指派的右側可能不是強制轉換運算式
  • CS0459無法採用唯讀區域變數的位址
  • CS0821隱含型別的區域變數無法固定
  • CS1641固定大小緩衝區欄位必須在欄位名稱之後具有陣列大小指定元
  • CS1642固定大小緩衝區欄位只能是結構體的成員
  • CS1656無法指派給 'variable',因為它是 '唯讀變數類型'
  • CS1663固定大小緩衝區類型必須是下列其中一項:boolbyte、或shortintlongcharsbyteushortuintulongfloatdouble
  • CS1664長度為「長度」且類型為「類型」的固定緩衝區太大
  • CS1665固定大小緩衝區的長度必須大於零
  • CS1666您無法使用未鎖定運算式中包含的固定大小緩衝區。嘗試使用 fixed 語句。
  • CS1708固定大小緩衝區只能透過區域變數或欄位存取
  • CS1716請勿使用 'System.Runtime.CompilerServices.FixedBuffer' 屬性。請改用「固定」欄位修飾符。
  • CS1919不安全的型別 'type name' 不能用於建立物件
  • CS4004無法 await 於不安全的上下文中
  • CS7092固定緩衝區只能有一個維度。
  • CS8372不要在屬性上使用 'System.Runtime.CompilerServices.FixedBuffer' 屬性
  • CS8385給定的表達式不能用於固定語句
  • CS8500這會取得受控型別 ('type') 的位址、大小,或宣告指向該型別的指標
  • CS8812無法將 & 方法群組的 'method' 轉換成非函式指標型別的 'type'。
  • CS9049固定欄位不能是參考欄位。
  • CS9123不應該在非同步方法中的參數或區域變數上使用 '&' 運算子。
  • CS9360此操作僅能在不安全情境中使用
  • CS9361stackalloc 不含初始化器的 SkipLocalsInit 表達式只能在不安全情境中使用
  • CS9362:「成員」必須在不安全的語境中使用,因為它被標記為「」unsafe
  • CS9363:「 成員」必須在不安全的語境中使用,因為它的簽名中有指標
  • CS9364不安全成員「member」無法覆蓋安全成員「member」
  • CS9365不安全成員「member」無法隱含實作安全成員「member」
  • CS9366不安全成員「成員」無法實作安全成員「成員」
  • CS9367RequiresUnsafeAttribute 無法套用於此符號。
  • CS9368RequiresUnsafeAttribute 僅在更新後的記憶體安全規則下有效。
  • CS9376若要滿足「泛型型別或方法」中型別參數「type parameter」的unsafe條件約束,標示為「new()」的建構函式「constructor」必須位於 unsafe 內容中
  • CS9377根據現行記憶體安全規則,'unsafe' 修飾符在此處沒有影響。
  • CS9379請不要在原始碼中使用「RequiresUnsafeAttribute'';改用「'unsafe'修飾符。
  • CS9388「'safe' 修飾符只能用於extern未標示 'unsafe'' 的成員。
  • CS9389:「extern成員必須標示為『unsafe」或“safe''。”
  • CS9390兩個部分成員宣告都必須標註「safe」,或者兩者都不可標註「safe
  • CS9392:在明確或擴展版面類型中,欄位必須標示為「unsafe」或「safe」。
  • CS9396無法在屬性或索引器「property」及其附屬工具上指定「unsafe'' 或 'safe' 修飾符。移除其中一根。
  • CS9397無法在屬性或索引子 'property' 的所有存取子上指定相同的 'unsafe' 或 'safe' 修飾詞。而應改為將該修飾詞放在屬性本身上。
  • CS9398不能在「fixed」陳述的語境下等待

指標操作和解引用

  • CS0193*->運算子必須套用在指標上
  • CS0196指標只能由一個值編製索引
  • CS0242問題中的作業在 void 指標上未定義

若要正確使用指標操作,請遵循取消引用、索引和算術運算的規則。 如需詳細資訊,請參閱 指標類型函式指標

  • 僅將 *-> 運算子套用到資料指標(CS0193)。 請勿將這些運算子與非指標類型或函式指標搭配使用。 與 C/C++ 不同,C# 中無法取消引用函式指標。
  • 只有一個值的索引指標 (CS0196)。 指標不支援多維索引。
  • 避免在 void 指標上未定義的作業 (CS0242) 。 例如,不要遞增 void 指標,因為編譯器不知道所指向之資料的大小。

指標型別和受管理型別

  • CS0208無法取得受管理類型('type')的位址、取得其大小,或宣告指向它的指標
  • CS0233:「 識別碼」沒有預先定義的大小,因此 sizeof 只能在不安全的內容中使用
  • CS8500這會取得受控型別 ('type') 的位址、大小,或宣告指向受控型別 ('type') 的指標

若要正確使用指標和 sizeof 運算子,請使用非受控類型和適當的內容。 如需詳細資訊,請參閱 非受控類型sizeof 運算子

  • 僅將指標與非受控類型搭配使用 (CS0208) 。 請勿取得受控類型的位址、計算受控類型的大小或宣告指向受控類型的指標。 受控類型包括包含參考類型欄位或屬性的參考類型和結構。
  • 在類型大小不是編譯時間常數的情境中使用sizeof運算子unsafeCS0233)。
  • 避免取得受管理型別的位址、取得其大小,或宣告指向受管理型別的指標(CS8500)。 當編譯器偵測到指標操作於受管理型別時,會觸發此警告(第 4 級)。 受管理型態是任何參考型別,或任何包含參考型態作為欄位或屬性的結構體。 如需詳細資訊,請參閱 非受控類型

固定語句的使用

  • CS0209固定語句中宣告的本地類型必須是指標型態
  • CS0210您必須在固定或 using 陳述式宣告中提供初始化運算式
  • CS0211無法取得給定運算式的位址
  • CS0212您只能在固定陳述式初始化運算式內取得未固定運算式的位址
  • CS0213您無法使用 fixed 陳述式來取得已固定運算式的位址
  • CS0254固定語句指派的右側不能是強制轉換運算式
  • CS0459無法取唯讀的區域變數的位址
  • CS0821:隱 式型別的本地變數無法修正
  • CS1656無法指派給 'variable',因為它是 '唯讀變數類型'
  • CS8385給定的表達式不能用於固定語句

當您不正確地使用 fixed 陳述式 時,就會發生這些錯誤。 此 fixed 陳述式可防止垃圾回收器重新定位可移動變數,並宣告指向該變數的指標。 欲了解更多資訊,請參閱 不安全程式碼與指引

若要正確使用fixed語句:

  • 將變數宣告為指標類型 (CS0209) 。
  • fixed 陳述式宣告中提供一個初始化器(CS0210)。
  • 只使用有效運算式的位址:欄位、區域變數和指標間接 (CS0211)。 不要將計算表達式的地址視為兩個變量的總和。
  • 僅在fixed陳述式初始化運算式內對未固定運算式使用位址運算子(CS0212)。
  • 請勿在已修正的表達上使用 fixed 陳述式 (CS0213)。 方法中的 unsafe 局部變數和參數已經固定在堆疊上。
  • 請勿在語句指派的 右側使用類型轉換表達式 (CS0254
  • 請勿採用唯讀區域變數的位址 (CS0459) 。 迴圈、foreach陳述式和using陳述式中的fixed變數是唯讀的。 此錯誤已不再在現有版本的編譯器中產生。
  • 使用明確類型,而不是在 var 陳述式中使用 fixedCS0821)。
  • 請勿指派給唯讀內容中的變數,例如 foreach 迴圈、 using 陳述式或 fixed 陳述式 (CS1656)。
  • 僅使用支援在 fixed 陳述式中進行釘選的運算式(CS8385)。 表達式必須是可尋址的變數、字串,或實作適當 GetPinnableReference 方法的型別。

不安全的上下文要求

  • CS0214指標和固定大小緩衝區只能在不安全的內容中使用
  • CS0227只有在使用 /unsafe 編譯時,才會出現不安全的程式代碼
  • CS0244:在指標類型上「」或「is」均無效。
  • CS1919不安全的類型 'type name' 無法用於物件建立
  • CS4004在不安全的情境下無法使用await
  • CS9123:在非同步方法中,運算子&不應用於參數或本地變數
  • CS9360此操作僅能在不安全情境中使用
  • CS9361stackalloc 不含初始化器的 SkipLocalsInit 表達式只能在不安全情境中使用
  • CS9362:「成員」必須在不安全的語境中使用,因為它被標記為「」unsafe
  • CS9363:「 成員」必須在不安全的語境中使用,因為它的簽名中有指標
  • CS9376:若要讓標示為「new()」的建構函式 'constructor' 滿足 'generic type or method' 中類型參數 'type parameter' 的「unsafe」限制,必須使用不安全內容
  • CS9398不能在「fixed」陳述的語境下等待

這些診斷發生在你使用不安全的程式碼結構且缺乏必要的 unsafe 上下文,或嘗試不允許的不安全型別操作時。 欲了解更多資訊,請參閱 Unsafe 程式碼與指標及關鍵字。unsafe

  • 使用關鍵字 (unsafe) 標示使用指標或固定大小緩衝區的方法、類型或程式碼區塊。 編譯器要求任何使用指標類型或固定大小緩衝區欄位的程式碼,必須有明確且不安全的上下文。
  • 請在專案設定中啟用 AllowUnsafeBlocks 編譯器選項(CS0227)。 若無此選項,編譯器會拒絕所有 unsafe 區塊,即使程式碼本身正確。
  • 請勿將 isas 運算子用於指標型別(CS0244)。 這些型別測試運算子不適用於指標,因為指標不參與型別階層。
  • 請勿使用 new 運算子來建立指標類型實例 (CS1919)。 若要在非受控記憶體中建立物件,請使用互通性來呼叫傳回指標的原生方法。
  • CS4004 當作舊有指引。 在 C# 14 及更早版本中, await 不允許進入不安全的環境。 根據 C# 15 預覽版中的記憶體安全性變更,await 可在 unsafe 內容中使用,因此這項一概而論的限制已不再符合目前的規則。
  • 請勿在非同步方法中的參數或區域變數上使用位址運算子(&)(CS9123)。 當非同步操作在暫停點後恢復時,該變數可能不存在於堆疊中。
  • 對於涉及不安全結構(如指標解參照、位址或 sizeof 非管理型態)的操作,請以 unsafe 關鍵字(CS9360)標示。 根據 C# 15 更新的記憶體安全規則,編譯器會識別需要不安全上下文的個別操作。
  • 當該屬性套用時,對於沒有初始unsafe化器的表達式(stackalloc)請使用關鍵字SkipLocalsInit。 若無初始化器,堆疊配置的記憶體會包含未初始化的資料,這是不安全的操作。
  • 呼叫標記為 unsafeCS9362 的成員,或簽名中帶有指標的成員(CS9363)時,請使用unsafe上下文。 在更新後的記憶體安全模型下,編譯器會為明確向呼叫者傳遞安全義務的成員報告 CS9362,對於簽章本身包含指標的舊有相容性案例則報告 CS9363。
  • unsafe 條件約束要求呼叫標示為 的建構函式時,請使用 new() 內容 (unsafe)。 泛型實例會隱式呼叫建構子,因此呼叫上下文必定不安全。
  • await 移到 fixed 陳述式 的主體或初始化運算式之外(CS9398)。 C# 15 預覽版允許在 unsafe 內容中使用 await,但 fixed 陳述式的釘選存留期仍無法跨越非同步暫止點。 在進入 fixed前先等待操作,或在等待前退出 fixed 語句。

不安全成員安全契約

  • CS9364不安全的成員「member」不能覆蓋安全的成員「member」
  • CS9365不安全成員「member」無法隱式實作安全成員「member」
  • CS9366不安全成員「member」無法實作安全成員「member」
  • CS9367RequiresUnsafeAttribute 無法套用於此符號。
  • CS9368RequiresUnsafeAttribute 僅在更新後的記憶體安全規則下有效。
  • CS9377根據現行記憶體安全規則,'unsafe' 修飾符在此處沒有影響。
  • CS9379請不要在原始碼中使用「RequiresUnsafeAttribute'';改用「'unsafe'修飾符。
  • CS9388「'safe' 修飾符只能用於extern未標示 'unsafe'' 的成員。
  • CS9389extern」成員必須標記為「unsafe」或「safe」。
  • CS9390兩個部分成員宣告都必須標記為「safe」,或兩者皆不可標記為「safe
  • CS9396無法在屬性或索引器「property」及其附屬工具上指定「unsafe'' 或 'safe' 修飾符。移除其中一根。
  • CS9397無法在屬性或索引子「property」的所有存取子上指定相同的「unsafe」或「safe」修飾詞。而應將該修飾詞指定在屬性本身。

這些診斷強制執行C# 15安全合約中對標示為不安全的成員的規則。 編譯器確保不安全的成員不會違反基底類別與介面所建立的安全規範。 欲了解更多資訊,請參閱 Unsafe 程式碼與指標及關鍵字。unsafe

  • 不要用不安全的成員(CS9364)覆蓋安全的基地成員。 覆寫必須保留基座成員的安全合約。 如果基座成員安全,覆蓋裝置也必須安全。 請移除覆蓋成員上的修飾符 unsafeRequiresUnsafeAttribute,或將基礎成員標記為不安全。
  • 不要隱含地實作一個安全介面成員與不安全成員(CS9365)。 當型別隱含實作介面成員時,呼叫者透過介面預期操作是安全的。 移除實作成員中的不安全標記,或使用明確的介面實作。
  • 不要顯式實作安全介面成員與不安全成員(CS9366)。 即使有明確實作,介面成員的安全合約仍必須被保留。
  • 僅適用於 RequiresUnsafeAttribute 支援的符號類型(CS9367)。 此屬性可套用於方法、屬性、事件、建構子與型別,但並非所有符號類型都支援此功能。
  • 啟用更新後的記憶體安全規則(RequiresUnsafeAttributeCS9368)。 此屬性是 C# 15 精煉記憶體安全模型的一部分,並未被舊有規則認可。 確保你的專案目標語言版本能支援更新規則。
  • 當修飾符沒有效果時移除 unsafeCS9377)。 根據現行的記憶體安全規則,某些情境不需要或不會從unsafe修飾符中受益。 編譯器會在修飾符無意義時警告,讓你能清理不必要的註解。
  • 請直接在unsafe成員宣告中使用修飾符,而不是在原始碼(RequiresUnsafeAttribute)套用。 該屬性僅用於元資料表示;在原始碼中, unsafe 關鍵字是正確的機制。
  • 僅將 safe 修飾元套用至尚未標示為 externunsafe 成員(CS9388)。 修 safe 飾符明確將外部成員排除在外部宣告的預設不安全假設之外。
  • 將每位 extern 成員標記為其中之一 unsafesafeCS9389)。 根據更新後的記憶體安全規則,外部成員必須明確宣告他們的安全合約,因為編譯器無法驗證實作。
  • 確保兩個部分成員宣告在 safe 修飾詞上保持一致(CS9390)。 若其中一份部分聲明標示 safe為 ,則另一份也必須標示 safe ,以維持安全合約的一致性。
  • safeunsafe 放在屬性或索引子上,或放在存取子上,但不要兩者同時放置(CS9396)。 如果該屬性為所有存取子定義了契約,請將修飾詞套用至屬性本身。 如果只有一個存取器不同,就把修飾符放在該存取器上,並保持屬性不變。
  • 如果屬性或索引器的每個存取子都有相同的 unsafesafe 修飾詞,請將該修飾詞移至屬性或索引器宣告(CS9397)。 只有當存取器故意不同時才使用存取者修飾符。

明確或擴展版面欄位

  • CS9392:在明確或擴展版面類型中,欄位必須標示為「unsafe」或「safe」。

在更新後的記憶體安全性模型下,當實例欄位參與明確或延伸配置,而宣告未說明該欄位是 unsafe 還是 safe 時,就會出現此診斷。 欲了解更多資訊,請參閱 Unsafe 程式碼與指標及關鍵字。safe

  • 在類型中,將每個執行個體欄位以 [StructLayout(LayoutKind.Explicit)][ExtendedLayout] 標記為 unsafesafe 其中之一(CS9392)。 如果該欄位是為自動屬性、欄位支持屬性、主要建構參數或類欄位事件而合成,則將修飾符放在擁有該產生欄位的屬性、參數或事件上。

固定大小緩衝區

  • CS1641固定大小緩衝區欄位必須在欄位名稱之後具有陣列大小指定元
  • CS1642固定大小的緩衝區欄位只能是結構的成員
  • CS1663固定大小緩衝區類型必須為以下之一:boolbyteshortintlongcharsbyteushortuintulongfloatdouble
  • CS1664長度為 'length' 且類型為 'type' 的固定大小緩衝區太大
  • CS1665固定大小緩衝區的長度必須大於零
  • CS1666你不能使用包含在未固定表達式中的固定大小緩衝區。試著用固定語句。
  • CS1708固定大小緩衝區只能透過區域變數或欄位存取
  • CS1716不要使用 'System.Runtime.CompilerServices.FixedBuffer' 屬性。改用「固定」欄位修飾符。
  • CS7092固定緩衝區只能有一個維度。
  • CS8372不要在屬性上使用 'System.Runtime.CompilerServices.FixedBuffer' 屬性
  • CS9049固定欄位不能是參考欄位。

當您使用固定大小的緩衝區時,會發生這些錯誤。 固定大小緩衝區是直接內嵌在結構中的陣列,主要用於互操作案例。 如需詳細資訊,請參閱 固定大小緩衝區

若要正確宣告及使用固定大小緩衝區:

  • 使用正整數常數 (CS1641CS1665) 指定欄位名稱之後的陣列大小。 緩衝區的總大小(元素數量乘以元素大小)不得超過 2^31 位元組(CS1664)。
  • 只在結構中宣告固定大小的緩衝區,而不是在類別中宣告 (CS1642) 。 如果您需要類別中的欄位,請使用常規陣列。
  • 使用其中一個支援的元素類型:boolbyteshortintlongcharsbyteushortuintulongfloatdoubleCS1663)。
  • 在存取緩衝區之前,使用 fixed 陳述式先鎖定包含的結構體(CS1666)。
  • 只能透過局部變數或欄位存取固定大小的緩衝區,而不是透過中間運算式 (CS1708) 。
  • 使用 fixed 欄位修飾元,而不是 System.Runtime.CompilerServices.FixedBuffer 屬性 (CS1716)。 也不要把這個屬性套用到屬性(CS8372)。
  • 宣告僅有一維的固定緩衝區(CS7092)。 不支援多維固定緩衝區。
  • 不要將固定大小的緩衝區宣告為 ref 欄位(CS9049)。 固定大小的緩衝區必須是值欄位。

函式指標

  • CS8812無法將 & 方法群組的 'method' 轉換成非函式指標型別的 'type'。

要取得函式指標,使用帶有明確函數指標類型 cast 的位址 of 運算子。 請勿使用 address-of 運算子 & 將方法群組指派給 void* 或其他非函式指標類型。 如需詳細資訊,請參閱 函式指標