こんにちは、Unityエンジニアのオオバです。

DOTweenをasync/await化して可読性の高いコードにしてみる件(キャンセルにも対応)

上の記事内で書いたソースにローカルメソッドを使ったのですが、それがどういう動きをするのか、Actionと何が違うのかを本記事では調べます。

👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!

ローカル関数はC#7から登場

ローカル関数はその名の通り、関数内に定義でき、その関数内でしか参照できない関数です。C#7から登場なので、Unity使いにとっては比較的最近使えるようにな機能ということになります。

Actionとどう違うのか?

同じような機能はActionでも実装可能です。

恒例のSharpLabで、どのようにIL前のC#にコンパイルされるか調査してみます。

以下が検証コードです。

using System;  

public class C  
{
    public void M()  
    {
        Action a =()=>{ Console.WriteLine("hoge"); };  
        a();  
    }

    public void N()  
    {
        void b(){ Console.WriteLine("hoge"); };  
        b();  
    }
}

コンパイルされたC#はこうなる

全ソースはコチラ

public class C  
{
    [Serializable]  
    [CompilerGenerated]  
    private sealed class c  
    {
        public static readonly c 9 = new c();  

        public static Action 9__0_0;  

        internal void b__0_0()  
        {
            Console.WriteLine("hoge");  
        }
    }

    public void N()  
    {
        g__b|1_0();  
    }

    [CompilerGenerated]  
    private static void g__b|1_0()  
    {
        Console.WriteLine("hoge");  
    }
}

中身を見ていきます。

ローカル関数の処理

  1. ローカル関数bをprivate関数として関数Nの外に出す
  2. N関数がb関数を呼ぶ

というシンプルな処理になっています。

Actionの処理

  1. 事前にActionで定義された処理を含むprivate classを定義
  2. private classのstaticなインスタンスを生成しておく
  3. M関数実行初回にActionオブジェクトを生成(2度目以降はprivate classのstatic変数のキャッシュを利用)
  4. private classに定義したActionの処理を実行

ローカル関数と比べると複雑で且つ結構重ための処理をしています。

結論

メモリアロケーション、CPU負荷の観点から、Actionとローカル関数のスワップが可能であれば、ローカル関数を使用すべきという結論に至りました。

個人的に実戦でローカル関数をあまり使用した経験がないので、何かトラブルがあったら、また報告させていただきます。

参考

オススメ記事