はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【Unity,C#】静的コンストラクタのついてまとめてみる

はじめに

今回は静的コンストラクタのついての記事になります!

私はUnityのScriptableObjectを読み込む際にプロパティを用いて以下のようなコードを書くことがあります。

private static SomeScriptableObject _hoge = null;
public static SomeScriptableObject Hoge => _hoge ?? (_hoge = Resources.Load<SomeScriptableObject>("Path"));

別にScriptalbeObjectに限らずJsonなんかでも、ずっと情報を保持しておいてほしいデータは初回のみ検索をしてそれ以降はキャッシュします。

ただこれでも全然いいのですが、これ以外の方法を知ったのでそちらも書き残しておきたいと思います。

静的コンストラクタ

コンストラクタとはクラスや構造体のインスタンスを生成するときに実行される初期化用のメソッドのことです。

私は恥ずかしながらずっと知らなかったのですが、インスタンスの生成のためではなく初のインスタンスが作成される前、または静的メンバーが参照される前に実行される静的コンストラクタというものもあるみたいです。
docs.microsoft.com


特にUnityではコンポーネントとしてアタッチするというインスタンス化方法もあるので少しややこしいですが、使ってみるととても便利な代物だと思います。


静的コンストラクタの私からみて大切そうな特徴をまとめてみました。

  • 静的コンストラクターはアクセス修飾子を取らず、パラメーターはなし
  • クラスまたは構造体は、静的コンストラクターを 1 つだけ持つことができる
  • 静的コンストラクターは、最初のインスタンスが作成され前、または静的メンバーが参照される前に、クラスを初期化するために自動的に呼び出される
  • static readonlyとして宣言されているフィールドは、その宣言の一部として、または静的コンストラクター内でのみ、割り当てることができる

静的コンストラクター - C# プログラミング ガイド | Microsoft Docs

public class Hoge
{
    static Hoge()
    {
        Debug.Log("静的コンストラクタ");
    }
}

実行の順番

いくつかの例をみてみるとかなり概要が掴めるかもしれません。

静的クラス+静的コンストラクタ

public class Test : MonoBehaviour
{
    private void Start()
    {
        Debug.Log("Start");
        var a = Hoge.Value;
    }
}

public static class Hoge
{
    public static int Value = 1;
    static Hoge()
    {
        Debug.Log("静的コンストラクタ");
    }
}
Start
静的コンストラクタ

MonoBehaviour+静的コンストラクタ

public class Test : MonoBehaviour
{
    static Test()
    {
        Debug.Log("静的コンストラクタ");
    }

    private void Awake()
    {
        Debug.Log("Awake");
    }

    private void Start()
    {
        Debug.Log("Start");
    }
}
静的コンストラクタ
Awake
Start

インスタンス化+静的コンストラクタ

public class Test : MonoBehaviour
{
    private void Start()
    {
        Debug.Log("Start");
        var b = new Fuga();
        var c = new Fuga();
    }
}

public class Fuga
{
    public Fuga()
    {
        Debug.Log("コンストラクタ");
    }

    static Fuga()
    {
        Debug.Log("静的コンストラクタ");
    }
}
Start
静的コンストラクタ
コンストラクタ
コンストラクタ

さいごに

初期化をする処理のひとつとして覚えておいた方がよいかもしれません。

最初の例において、プロパティで定義するか静的コンストラクタで定義するべきか私には分かりませんが選択肢としてはありだと思います。

ではまた。