解決建構子宣告與模組初始化器的錯誤與警告

本文涵蓋下列編譯程序錯誤:

  • CS0132:「 建構子」:靜態建構子必須是無參數的。
  • CS0514:靜態建構函式不能有明確的 'this' 或 'base' 建構函式呼叫。
  • CS0515:靜態建構函式不允許使用 存取修飾詞。
  • CS0516:建構函式「建構函式」不能呼叫自身。
  • CS0517:'class' 沒有基類,而且無法呼叫基底建構函式。
  • CS0522:結構無法呼叫基類建構函式。
  • CS0526: 介面不能包含實例建構子。
  • CS0568:結構不能包含明確的無參數建構函式。
  • CS0573:「 欄位宣告」:結構體中不能有實例欄位初始化器。
  • CS0710:靜態類別不能有實例建構函式。
  • CS0768:建構函式無法透過另一個建構函式呼叫自己。
  • CS1018: 關鍵字 'this' 或 'base' 預期。
  • CS8054:列舉型別不能包含明確的無參數建構函式。
  • CS8091:不能是 extern 且具有建構函式初始化運算式。
  • CS8358: 無法使用屬性建構器,因為它有「in」或「ref readonly」參數。
  • CS8760:「 事件」:外部事件不能有初始化器。
  • CS8813: 模組初始化器必須是普通成員方法
  • CS8814: 模組初始化器方法「方法」必須在模組層級可存取
  • CS8815: 模組初始化方法「方法」必須是靜態且非虛擬的,必須沒有參數,且必須回傳「void」
  • CS8816:模組初始化方法「方法」不得為通用型,且不得包含於一般型別中
  • CS8861:非預期的自變數清單。
  • CS8862:具有參數列表的類型中宣告的建構函式必須具有 'this' 建構函式初始化表達式。
  • CS8867:基底類型 '{0}' 中找不到可存取的複製建構函式。
  • CS8868:記錄中的複製建構函式必須呼叫基底的複製建構函式,或者如果記錄繼承自 物件,則為無參數物件建構函式。
  • CS8878:複製建構函式 '{0}' 必須是公開的或受保護的,因為紀錄未密封。
  • CS8900: 模組初始化器不能被歸因於「UnmanagedCallersOnly」。
  • CS8901:「 method」被歸屬為「UnmanagedCallersOnly」,無法直接呼叫。取得一個函式指標指向此方法。
  • CS8902:「 method」被歸屬性為「UnmanagedCallersOnly」,無法轉換成代理型別。取得一個函式指標指向此方法。
  • CS8910:主要建構函式與合成複製建構函式衝突。
  • CS8958:無參數結構建構函式必須是 'public'。
  • CS8982:在 'struct' 中宣告的建構子其參數清單必須包含一個 'this' 初始化器,該初始化器須呼叫主建構子或明確宣告的建構子。
  • CS8983:具有欄位初始化表達式的 'struct' 必須包含明確宣告的建構函式。
  • CS9105:無法在此內容中使用主要建構函式參數。
  • CS9106: 此內容中的類型和參數之間的標識符模棱兩可。
  • CS9108:無法使用在匿名方法、Lambda 運算式、查詢運算式或本機函式內具有類似 ref 類型的參數。
  • CS9109:無法在實例成員內使用 ref、out或 in 主要建構函式參數。
  • CS9110:無法使用在實例成員內具有類似 ref 類型的主要建構函式參數。
  • CS9111:結構實例成員內的匿名方法、Lambda 運算式、查詢表達式和本機函式無法存取主要建構函式參數。
  • CS9112:結構體中的匿名方法、Lambda 運算式、查詢運算式和本地函式,無法存取同時用於實例成員的主建構函式參數。
  • CS9114:只讀型別的主要建構子參數不能被指派(只在型別的 init-only setter 或變數初始化中例外)。
  • CS9115:無法通過可寫入參考傳回屬於只讀類型的主建構函式的參數。
  • CS9116:只讀類型的主要建構函式參數不能作為 ref 或 out 值使用(僅限於 init 專用的 setter 或變數初始化器中除外)。
  • CS9117:不能修改唯讀類型的主要建構函式參數成員(除非在類型的初始化設定器或變數的初始化中進行)。
  • CS9118:不可使用可寫入的參考傳回只讀類型的主要建構函式參數的成員。
  • CS9119:只讀類型之主要建構函式參數的成員不能當做 ref 或 out 值使用(除了類型或變數初始化表達式的 init-only setter 除外)。
  • CS9120:無法按引用傳回主要建構函式參數。
  • CS9121:型別的結構主要建構函式參數會導致結構配置中的迴圈。
  • CS9122:非預期的參數清單。
  • CS9136:無法在實例成員內使用類型的主要建構函式參數。
  • CS9343: 若沒有在型別宣告中加入參數清單,無法將參數傳遞給基底型別。

此外,本文還涵蓋以下警告:

  • CS0824:建構函式 'name' 被標記為外部。
  • CS9107:參數會被捕捉到外圍類型的狀態中,其值也會傳遞給基類建構函式。基類也可能會捕捉該值。
  • CS9113:未讀取參數 。
  • CS9124:參數已擷取到封入類型的狀態,其值也用於初始化欄位、屬性或事件。
  • CS9179:主要建構函式參數是由基底 的成員遮蔽
  • CS9018: 在自動實作屬性被明確指派前就被讀取,這會導致其先前隱含地指派為「default」。
  • CS9019:欄位在被明確指派前被讀取,造成其在此之前被隱含指派為「default」。
  • CS9020:在所有欄位被指派之前,已讀取「this」物件,這導致未明確指派的欄位會被先前隱含地指派為「default」。
  • CS9021: 控制權在自動實作屬性被明確指派前返回呼叫者,導致先前隱含的「default」指派。
  • CS9022: 在欄位被明確指定前,控制權已回傳給呼叫者,因而隐含地先指派了「default」。

靜態建構函式

  • CS0132:「 建構子」:靜態建構子必須是無參數的。
  • CS0514:靜態建構函式不能有明確的 'this' 或 'base' 建構函式呼叫。
  • CS0515:靜態建構函式上不允許 Access 修飾詞。

靜態建構子會初始化型別的靜態資料。 如需詳細資訊,請參閱 靜態建構函式。

為了更正這些錯誤,請確保您的靜態建構子宣告符合以下規則:

  • 移除靜態建構子宣告中的所有參數,因為靜態建構子必須是無參數的(CS0132)。 如果你需要傳遞初始化值,可以考慮使用你在靜態建構器執行前設定的靜態欄位或屬性。
  • 移除靜態建構函式中的任何存取修飾符,例如 public、protected、private 或 internal,因為執行時期會控制靜態建構函式的執行時間,所以存取修飾符不具意義(CS0515)。
  • 移除靜態建構器中的任何 : base() 或 : this() 建構器初始化呼叫,因為靜態建構器無法串接到其他建構器(CS0514)。 執行時會自動呼叫基底類別的靜態建構子(如果存在的話)。

建構函式宣告

  • CS0526: 介面不能包含實例建構子。
  • CS0710:靜態類別不能有實例建構函式。
  • CS8054:列舉不能包含明確的無參數建構函式。
  • CS8358: 無法使用屬性建構器,因為它有「in」或「ref readonly」參數。
  • CS8091:建構函式不能是 extern 並具有建構函式初始化。
  • CS8760:「 事件」:外部事件不能有初始化器。

你只能在 class 和 struct 類型中宣告建構子,包括 record class 和 record struct 類型。 欲了解更多資訊,請參閱 實例建構子。

要修正這些錯誤,請嘗試以下建議:

  • 把建構子移到 class 或 struct 類型,因為在 interface 或 enum 類型中無法宣告建構子(CS0526, CS8054)。 介面定義合約,但不提供初始化邏輯,而列舉型別的值是在編譯時定義的。
  • 從靜態類別中移除實例建構子,因為靜態類別無法實例化,因此無法有實例建構子(CS0710)。 如果你需要初始化邏輯,可以用靜態建構器。
  • 在屬性建構子中將 in 或 ref readonly 參數更改為按值傳遞的參數,因為屬性建構子不支援 in 或 ref readonly 參數修飾符(CS8358)。 執行時透過反射來實例化屬性,但反射不支援 in OR ref readonly 修飾符。
  • 移除: base()建構子中的 : this() OR extern 建構器初始化器,因為外部建構子無法串接到其他建構子(CS8091)。 外部建構子的實作是由外部提供的,因此無法進行建構子串聯。
  • 移除事件宣告中的初始化器 extern (CS8760)。 外部事件的新增與移除存取器由外部程式碼提供,因此原始碼中的欄位初始化器不會生效,編譯器也不允許。

對於建構子宣告,可以產生以下警告:

  • CS0824:建構函式被標記為外部。

當建構子被標記 extern為 時,編譯器無法驗證實作的存在。 要抑制此警告,請提供非外部的實作,或確保外部實作已正確連結。

結構類型中的建構函式

  • CS0568:結構不能包含明確的無參數建構函式。
  • CS0573:「 欄位宣告」:結構體中不能有實例欄位初始化器。
  • CS8958:無參數結構建構函式必須是 'public'。
  • CS8982:在具有參數列表的 'struct' 中宣告的建構函式,必須有一個 'this' 初始化,該初始化需要呼叫主要建構函式或明確宣告的建構函式。
  • CS8983:具有字段初始化表達式的 'struct' 必須包含明確宣告的建構函式。

結構型別有特定的建構子和欄位初始化規則。 欲了解更多資訊,請參閱結構類型文章中的結構初始化與預設值章節。

要修正這些錯誤,請嘗試以下建議:

  • 若遇到 CS0568 或 CS0573,請升級至 C# 10 或更新版本,因為這些錯誤僅發生在較舊版本的 C# 中。 現代 C# 允許在結構中明確使用無參數建構子與欄位初始化器。
  • 請對任何無參數結構建構器加入 public 存取修飾符,因為無參數結構建構器必須公開,以確保 default 表達式與陣列配置能正確初始化結構實例(CS8958)。
  • 在有主建構子的結構中,為明確宣告的建構子加入 : this(...) 初始化器,因為所有非無參數建構函式必須串接到主建構子或其他明確宣告的建構函式,以確保初始化一致性(CS8982)。
  • 當你的結構體使用欄位初始化器時,請宣告明確的建構子,因為編譯器需要明確的建構子來確保欄位初始化器被呼叫(CS8983)。 這個建構子可以是無參數且沒有內容的建構子。

以下警告表示欄位或屬性在讀取前未被明確指派,或在控制權返回呼叫者之前:

  • CS9018:自動實作屬性在明確指派前會被讀取,這會導致之前隱含地指派了「預設值」。
  • CS9019:欄位在被顯式指派前被讀取,導致先前的「default」隱含指派。
  • CS9020:在所有欄位被指派值之前,「this」物件已被讀取,導致所有未明確指派的欄位被隱含地指派為「default」值。
  • CS9021: 控制權在自動實作屬性被明確指派之前就返回給呼叫者,導致先前進行了隱含的預設值指派。
  • CS9022:在欄位被明確指派之前,控制權會回傳給呼叫者,這會導致先前隱含的「default」指派。

為了消除這些警告,請在讀取欄位與自動實作屬性前,或在建構子回傳控制前,明確指派所有欄位與自動實作屬性(CS9018、CS9019、CS9020、CS9021、CS9022)。 如果讀取未指派的成員,編譯器會隱含地將default指派給它們,這可能不是預期的行為。

使用 base 和 this 的建構函式呼叫

  • CS0516: 建構函式不能呼叫自己。
  • CS0517:「 類別」沒有基底類別,無法呼叫基底建構子。
  • CS0522:結構無法呼叫基類建構函式。
  • CS0768:建構函式無法透過另一個建構函式呼叫自己。
  • CS1018: 關鍵字『this』或『base』預期出現。

透過使用建構器初始化器,一個建構者可以透過使用 : this() 或 : base()呼叫另一個建構器。 欲了解更多資訊,請參見 使用建構函數。

要修正這些錯誤,請嘗試以下建議:

  • 打破任何循環的建構子呼叫鏈,因為建構子無法直接或間接透過另一個建構器呼叫自己(CS0516, CS0768)。 確保建構子鏈結最終能夠在結束時到達一個不會呼叫同類型其他建構子的建構子。
  • 在結構型別的建構子中或在 : base() 的建構子中,移除 System.Object 初始化元,因為這些型別沒有可呼叫的基底類別建構子(CS0517,CS0522)。 結構型別隱含地繼承自 System.ValueType,但你無法明確呼叫它的建構子。
  • 完成建構子初始化或移除建構子宣告中的冒號:,因為當冒號緊接建構子簽章時,編譯器預期會執行this()或base()(CS1018)。 如果沒有鏈式連結,請加入適當的建構子呼叫,或是完全移除冒號。

記錄和複製建構函式

  • CS8867:基底類型中找不到可存取的複製建構函式。
  • CS8868:記錄中的複製建構函式必須呼叫基底的複製建構函式,或是記錄繼承自 物件時,無參數物件建構函式。
  • CS8878:複製建構函式必須公開或保護,因為記錄未密封。
  • CS8910:主要建構函式與合成複製建構函式衝突。

在衍生記錄型態中,你的明確複製建構器必須透過初始 : this() 化器呼叫該基型的複製建構器。 如果記錄直接繼承自 System.Object,則可呼叫無參數物件建構器(CS8868)。

記錄 包含一個由編譯器合成的 複製建構器。 你可以寫明確的複製結構,但必須符合特定要求。 當記錄複製構造器違反以下要求時,編譯器會產生錯誤:

  • 基底型態必須有一個可存取的複製建構器。 所有 record 類型都有複製建構器。 確保基礎型態為 record,或加入可存取的複製構造子(CS8867)。
  • 在衍生記錄型態中,你的明確複製建構器必須透過初始 : base() 化器呼叫該基型的複製建構器。 如果記錄直接繼承自 System.Object,則可呼叫無參數物件建構器(CS8868)。
  • 複製構造器必須是 public ,或 protected 除非記錄類型為 sealed。 在複製建構器(CS8878)中加入適當的存取修正符。
  • 如果你的明確複製建構子與合成複製建構子的簽名相同,定義就會衝突。 移除您的明確複製構造子或修改其簽名(CS8910)。

模組初始化器宣告

  • CS8813: 模組初始化器必須是普通成員方法。
  • CS8814: 模組初始化方法「方法」必須在模組層級可存取。
  • CS8815: 模組初始化方法「方法」必須是靜態且非虛擬的,必須沒有參數,且必須回傳「void」。
  • CS8816: 模組初始化器方法「方法」不得為通用型,且不得包含於通用型別中。
  • CS8900: 模組初始化器不能被歸因於「UnmanagedCallersOnly」。
  • CS8901:「 method」被歸屬為「UnmanagedCallersOnly」,無法直接呼叫。取得一個函式指標指向此方法。
  • CS8902:「method」被屬性標記為「UnmanagedCallersOnly」,無法轉換成委派類型。取得一個函式指標來指向此方法。

這些錯誤強制執行標記為 ModuleInitializerAttribute的方法的要求。 模組初始化器會在組件首次載入時自動執行,在該模組中任何其他程式碼執行之前。 完整規則請參見 模組初始化器。

要修正這些錯誤,請根據特定診斷進行以下其中一項變更:

  • 確保標記為 [ModuleInitializer] 的方法是一般方法,而非屬性存取子、事件存取子、區域函式、lambda、建構函式、解構函式或運算子(CS8813)。 編譯器只能將一般方法宣告視為模組初始化基礎架構的有效目標。
  • 將模組初始化方法及其所有包含的型別設為 internal 或 public,以確保該方法可以在頂層型別(CS8814)之外存取。 執行時需要從產生的模組層級程式碼呼叫方法,這需要模組層級的可及性。
  • 將模組初始化器方法宣告為 static,非虛擬,無參數,且有 void 回傳類型(CS8815)。 執行時會呼叫模組初始化器,且不帶任何參數,並捨棄結果,因此方法簽章必須完全符合這些限制。
  • 從模組初始化器方法中移除泛型參數,並將方法移出包含任何泛型型別(CS8816)。 執行時無法決定呼叫初始化器時要提供哪些型別參數,因此不允許使用通用方法和泛型型的方法。
  • 請從模組初始化器方法中移除UnmanagedCallersOnlyAttribute(CS8900)。 模組初始化器是由受管理的執行時基礎設施呼叫的,因此無法僅限於非管理呼叫者。
  • 請取得被標記為 [UnmanagedCallersOnly] 的方法的函式指標,而不是直接呼叫該方法 (CS8901). 標註為UnmanagedCallersOnlyAttribute的方法無法從受管理的程式碼中呼叫。 使用 & 運算子在 delegate* unmanaged<...> 上下文中取得函式指標(unsafe),並將該指標傳遞給非受控程式碼。 如果你的專案還不允許不安全的程式碼,請啟用 AllowUnsafeBlocks。
  • 取得函式指標,而不是將標記為 [UnmanagedCallersOnly] 的方法轉換成委派型別(CS8902)。 歸 UnmanagedCallersOnlyAttribute 屬於 的方法無法以管理代理來表示,因為呼叫慣例不相容。 在delegate* unmanaged<...>上下文中使用函式指標(unsafe)代替。 如果你的專案還不允許不安全的程式碼,請啟用 AllowUnsafeBlocks。

如需詳細資訊,請參閱 ModuleInitializerAttribute 和 UnmanagedCallersOnlyAttribute。

主要建構函式宣告

主要建構子 直接在型別宣告中宣告參數。 編譯器會為主要建構函數的參數合成一個欄位,以便於在成員或欄位初始化器中使用時儲存該參數。

建構子鏈

  • CS8861:非預期的自變數清單。
  • CS8862:在具有參數清單的類型中宣告的建構函式必須具有 'this' 建構函式初始化表達式。
  • CS9122:非預期的參數清單。
  • CS9343: 若沒有在型別宣告中加入參數清單,無法將參數傳遞給基底型別。

當一個型別有主建構子時,所有其他明確宣告的建構子必須使用 : this(...) 來連結至它。

要修正這些錯誤,請嘗試以下建議:

  • 新增一個 : this(...) 初始化器,將適當的參數傳遞給主要建構子,因為所有明確宣告的建構子必須與主要建構子(CS8862)串接。
  • 從已實現的介面或結構體或介面的基底型別清單中移除參數清單。 只有帶有參數列表的類別宣告,才能將參數傳給基底型清單中的基底類別(CS8861)。
  • 在將參數傳給基底類別前,先在導出型別宣告中加入參數清單,例如 class Derived(int value) : Base(value) { } (CS9343)。 基底類別必須有相符的建構子,但不需要主建構子。
  • 從宣告中移除主要建構子參數清單 interface ,因為介面不能有主建構子(CS9122)。

基底建構子呼叫中的參數使用

  • CS9105:無法在此內容中使用主要建構函式參數。
  • CS9106:標識元在此內容中類型與參數之間模棱兩可。

你只能在基礎建構器呼叫中使用主建構參數,前提是你把它們當作主建構器宣告的一部分。

要修正這些錯誤,請嘗試以下建議:

  • 將參數使用移至類型宣告的基底子句,而非在明確宣告的建構子 : base() 呼叫中使用,因為主要建構子參數只能出現在型別宣告的基底子句中(CS9105)。
  • 當一個型別與主要建構參數相同名稱時,請重新命名型別或參數,因為參考變得模糊(CS9106)。

類參考型參數

  • CS9108:無法使用在匿名方法、Lambda 運算式、查詢運算式或本機函式內具有類似 ref 類型的參數。
  • CS9109:無法在實例成員內使用 ref、out或 in 主要建構函式參數。
  • CS9110:無法在實例成員中使用具有 ref 類型的主要建構函式參數。
  • CS9136:無法在實例成員內使用類型的主要建構函式參數。

為了修正這些錯誤:

  • ref struct 類型的主要建構器參數對於使用地點有特定限制。 將參數存取從 lambda 表達式、查詢表達式或本地函式(CS9108)中移除。 在非 ref struct的類型中,僅在欄位初始化器或建構子主體中存取 ref struct 參數,不包括實例成員(CS9110、 CS9136)。
  • 對於 ref struct 型別,你不能在實例方法或屬性存取器中使用包含 in、ref 或 out 修飾的主建構子參數。 將參數值複製到建構子中的欄位,並在實例成員中使用該欄位(CS9109)。

結構型別限制

  • CS9111:結構實例成員內的匿名方法、Lambda 運算式、查詢表達式和本機函式無法存取主要建構函式參數。
  • CS9112:結構體中的匿名方法、lambda 運算式、查詢運算式和區域函式,無法存取在實例成員中也使用的主要建構函式參數。
  • CS9120:無法以引用方式傳回主要建構函式參數。
  • CS9121:結構的主要建構函式的參數型別會導致結構佈局中的循環。

為了修正這些錯誤:

  • 在結構型態中,你無法在 lambda 表達式、查詢表達式或實例成員內的本地函式中擷取主要建構參數。 在使用這些情境前,先將參數複製到區域變數或欄位(CS9111、 CS9112)。
  • 你無法在結構型別中透過參考回傳主要建構參數。 將值儲存在欄位中,必要時以參考方式回傳該欄位(CS9120)。
  • 確保主要建構參數的型別不會在結構體配置中產生循環。 結構體不能直接或間接包含自身類型的欄位(CS9121)。

唯讀結構限制

  • CS9114:只讀類型的主要建構函式參數無法被重新賦值(除了在該類型的僅限初始化設定器或變數的初始化設定中)。
  • CS9115:唯讀類型的主建構函式參數不能透過可寫入的參考傳回。
  • CS9116:只讀類型的主建構函式參數不能作為 ref 或 out 值(除了在該類型的初始化設值器或變數初始值設置器中的僅用於 init 專用的設值器之外)。
  • CS9117:唯讀類型的主要建構函式參數無法被修改(除非在僅用於初始化的 setter 或變數初始化器中)。
  • CS9118:只讀類型的主要建構函式參數的成員不能以可寫入參考的方式傳回。
  • CS9119:只讀類型之主要建構函式參數的成員不能做為 ref 或 out 值(除了類型或變數初始化表達式的 init-only setter 除外)。

為了修正這些錯誤:

  • 在readonly struct類型中,你無法修改主要建構子的參數及其成員,除非使用僅供初始化的設定器或變數初始化器。 將指派移至欄位初始化器或僅初始化屬性設定器(CS9114、 CS9117)。
  • 你無法透過可寫引用在readonly struct型別中回傳主要建構函式參數及其成員。 請以參考傳遞 readonly ref 或改以值傳遞(CS9115、CS9118)。
  • 你無法在 ref 類型中將主要建構子參數及其成員作為 out 或 readonly struct 參數傳遞。 請以值或參數 in 方式傳遞(CS9116、 CS9119)。

針對捕捉及遮蔽參數的警告

  • CS9107: 參數被捕捉到包圍型態的狀態,其值也會傳遞給基底建構子。這個值也可能被基底類別捕捉。
  • CS9113: 參數未讀取。
  • CS9124:參數會擷取到封入類型的狀態,而且其值也可用來初始化欄位、屬性或事件。
  • CS9179:主要建構函式參數被基底類別的成員覆蓋。

以下警告表示您可能存在儲存或存取主要建構參數的方式問題:

  • 如果你們同時將參數傳給基礎建構子,並以衍生型態存取,可能會將參數儲存兩次。 你可能在基類有一個複本,而在衍生類中則有另一個。 請考慮是否需要兩個副本,或是重組程式碼以避免重複(CS9107)。
  • 如果你從沒看過主要建構參數,其實不需要它。 移除主要建構子宣告(CS9113)中未使用的參數。
  • 如果你在封閉型別中捕獲並用來初始化欄位、屬性或事件時,可能會儲存參數兩次。 考慮直接使用捕獲的參數,而非初始化獨立成員(CS9124)。
  • 當基底型別成員與主要建構函數參數同名時,基底型別成員會覆蓋該參數。 為避免混淆,請重新命名參數(CS9179)。