コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】遅延初期化クラス「Lazy」を使ってみる

使用例1

適用前

using UnityEngine;

public class Data
{
    private TextAsset m_textAsset;

    public TextAsset TextAsset
    {
        get
        {
            if ( m_textAsset == null )
            {
                m_textAsset = Resources.Load<TextAsset>( "hoge" );
            }
            return m_textAsset;
        }
    }
}

public class Example : MonoBehaviour
{
    private void Start()
    {
        var data = new Data();
        Debug.Log( data.TextAsset.text );
    }
}

適用後

using System;
using UnityEngine;

public class Data
{
    private readonly Lazy<TextAsset> m_textAsset =
        new Lazy<TextAsset>( () => Resources.Load<TextAsset>( "hoge" ) );

    public TextAsset TextAsset => m_textAsset.Value;
}

public class Example : MonoBehaviour
{
    private void Start()
    {
        var data = new Data();
        Debug.Log( data.TextAsset.text );
    }
}

例えば、初めて TextAsset プロパティにアクセスされた時に
Resources.Load で TextAsset を読み込む、といった使い方ができます

使用例2

using System;
using System.Linq;
using UnityEngine;

public class ItemValue
{
    public string m_itemName = "キズぐすり";

    public ItemValue()
    {
        Debug.Log( "コンストラクタが呼ばれました" );
    }
}

public class ItemData : Lazy<ItemValue>
{
    public int m_itemId;
}

public class Example : MonoBehaviour
{
    private void Start()
    {
        int count = 100;
        var list = new ItemData[ count ];
        for ( int i = 0; i < count; i++ )
        {
            list[ i ] = new ItemData { m_itemId = i };
        }
        var data = list.FirstOrDefault( c => c.m_itemId == 25 );
        Debug.Log( data.Value.m_itemName );
    }
}

例えば ItemData を 100個作成して、m_itemId が 25 の要素にのみアクセスした場合、

f:id:baba_s:20190415213806p:plain

ItemValue のコンストラクタは1回しか呼ばれません
(アクセスされた m_itemId が 25 の要素のコンストラクタのみ呼び出されている)