ネコのために鐘は鳴る

寺院に住み着くパソコ〇好き

(C#) ModuleInitializer からのみ呼べるメソッドを作る

小ネタです。C# 9 から ModuleInitializer 属性をつけると、アセンブリのロード時に一度のみ呼び出される処理を書くことができます。

プログラマが処理を差し込めるあらゆるタイミングの中で最も早く、Main メソッドより先に呼び出すことすら可能です。楽しいですね。型情報などのメタ情報のキャッシュなどの用途で利用できます。(用途についての詳細はここでは省略)

静的メソッドに [ModuleInitializer] とつけることで機能するのですが、制限として public または internal である必要があります。モジュール初期化としての自動呼出しでのみ使用したいので、プログラマが明示的にこのメソッドを呼べないようにしたいです。単にこのメソッドを呼ばないように気をつければいいだけなのですが、私はプログラマを信用していません。信用できるのはコンパイラだけ。(人間不信)

呼んではいけないものはコンパイルエラーにしたいです。

internal static class Foo
{
    [ModuleInitializer]
    [Obsolete("Don't call this method explicitly.", true)]
    internal static void MyInitialization()
    {
        // Do something here.
    }
}

[Obsolete] は非推奨 API を表すための属性で、第2引数を true にするとこのメソッドの呼び出しを書くとコンパイルエラーになります。

コンパイラが自動生成する、本来のモジュール初期化としての呼び出しはコンパイルエラーにはなりません。

若干 Obsolete の濫用な気がしますが、文法として正しいコードをコンパイルエラーにする方法が Obsolete 属性しかないので仕方がないです。 前にも 構造体の既定のコンストラクタを禁止する 記事で同じように Obsoleteコンパイルエラーにしていますが、他に方法がないんですよねぇ……