共用方式為


模組初始設定器

注意

本文是功能規格。 規格可作為功能的設計檔。 其中包含建議的規格變更,以及功能設計和開發期間所需的資訊。 這些文章會發佈,直到提議的規格變更完成並併併入目前的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()
    {
        // ...
    }
}

某些需求會加在將此屬性作為目標的方法上。

  1. 方法必須是 static
  2. 方法必須是無參數的。
  3. 方法必須傳回 void
  4. 方法不得為泛型或包含在泛型型別中。
  5. 方法必須可從包含的模組存取。
    • 這表示方法的有效可及性必須為 internalpublic
    • 這也表示方法不可以是區域函式。

在編譯中找到具有這個屬性的一或多個有效方法時,編譯程式會發出模組初始化表達式,其會呼叫每個屬性化方法。 呼叫會以保留但具決定性的順序發出。

缺點

為什麼我們 這樣做?

  • 對於要求這項功能的使用者而言,現有的第三方工具「插入」模組初始化運算式可能就已足夠。

設計會議

2020 年 4 月 8 日