模組初始設定器
注意
本文是功能規格。 規格可作為功能的設計檔。 其中包含建議的規格變更,以及功能設計和開發期間所需的資訊。 這些文章會發佈,直到提議的規格變更完成並併併入目前的ECMA規格為止。
功能規格與已完成實作之間可能有一些差異。 這些差異是在相關 語言設計會議(LDM)記錄中擷取的。
您可以在關於 規範的文章中深入了解將功能規格宣言納入 C# 語言標準的過程。
冠軍問題:https://github.com/dotnet/csharplang/issues/2608
總結
雖然 .NET 平臺具有 功能,直接支援撰寫元件的初始化程序代碼(在技術上為模組),但它不會在 C# 中公開。 這是一個相當小眾的情境,但一旦遇到它,解決方法似乎相當棘手。 有報導稱,一些客戶(包括Microsoft內外的客戶)正在面臨這個問題,毫無疑問,還有更多未記錄的情況。
動機
- 讓函式庫在載入時進行提前且一次性的初始化,並且要有最小的負擔,不需要使用者明確呼叫任何東西。
- 目前
static
建構函式方法的一個特定痛點是,運行時間必須對具有靜態建構函式的類型使用方式執行額外的檢查,才能決定是否需要執行靜態建構函式。 這會增加可測量的額外負荷。 - 讓原始碼產生器執行一些全域初始化邏輯,而無需用戶明確呼叫任何內容。
詳細設計
使用 [ModuleInitializer]
屬性標註方法,即可將方法指定為模組初始化器。
using System;
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class ModuleInitializerAttribute : Attribute { }
}
屬性可以使用如下:
using System.Runtime.CompilerServices;
class C
{
[ModuleInitializer]
internal static void M1()
{
// ...
}
}
某些需求會加在將此屬性作為目標的方法上。
- 方法必須是
static
。 - 方法必須是無參數的。
- 方法必須傳回
void
。 - 方法不得為泛型或包含在泛型型別中。
- 方法必須可從包含的模組存取。
- 這表示方法的有效可及性必須為
internal
或public
。 - 這也表示方法不可以是區域函式。
- 這表示方法的有效可及性必須為
在編譯中找到具有這個屬性的一或多個有效方法時,編譯程式會發出模組初始化表達式,其會呼叫每個屬性化方法。 呼叫會以保留但具決定性的順序發出。
缺點
為什麼我們 不 這樣做?
- 對於要求這項功能的使用者而言,現有的第三方工具「插入」模組初始化運算式可能就已足夠。