怎么做網(wǎng)站注冊(cè)登入頁(yè)面搜狗指數(shù)官網(wǎng)
? ? ? 如果某些字段在每個(gè)構(gòu)造函數(shù)中都要進(jìn)行初始化,很多人都喜歡在字段聲明時(shí)就進(jìn)行初始化,對(duì)于一個(gè)非繼承自MonoBehaviour的腳步,這樣做是沒(méi)有問(wèn)題的,然而繼承自MonoBehaviour后就會(huì)造成內(nèi)存的浪費(fèi),為什么呢?因?yàn)槔^承自MonoBehaviour的腳步的構(gòu)造函數(shù)可能會(huì)被多次執(zhí)行,這也是為什么Unity的Mono腳步不使用構(gòu)造函數(shù)的原因。而字段在聲明時(shí)賦值的結(jié)果其實(shí)是會(huì)在構(gòu)造函數(shù)中去執(zhí)行,即使沒(méi)有聲明構(gòu)造函數(shù),編譯器會(huì)在默認(rèn)的無(wú)參構(gòu)造函數(shù)中將你的字段初始化放到默認(rèn)的構(gòu)造函數(shù)中去。下面用一個(gè)簡(jiǎn)單的腳步進(jìn)行看一下:
public class Test : MonoBehaviour{private List<int> _data = new List<int>();public Test(){Debug.Log("構(gòu)造函數(shù)調(diào)用 -- Test");}void Start(){}}
上面這段代碼就是在聲明字段時(shí)就進(jìn)行了初始化,現(xiàn)在從IL代碼層面上去看一下:
.class public auto ansi beforefieldinit MagicWorld.Testextends [UnityEngine.CoreModule]UnityEngine.MonoBehaviour
{// Fields.field private class [netstandard]System.Collections.Generic.List`1<int32> _data// Methods.method public hidebysig specialname rtspecialname instance void .ctor () cil managed {// Method begins at RVA 0x3639// Header size: 1// Code size: 28 (0x1c).maxstack 8IL_0000: ldarg.0IL_0001: newobj instance void class [netstandard]System.Collections.Generic.List`1<int32>::.ctor() // _data = new List<int>();IL_0006: stfld class [netstandard]System.Collections.Generic.List`1<int32> MagicWorld.Test::_dataIL_000b: ldarg.0IL_000c: call instance void [UnityEngine.CoreModule]UnityEngine.MonoBehaviour::.ctor()IL_0011: ldstr "構(gòu)造函數(shù)調(diào)用 -- Test"IL_0016: call void [UnityEngine.CoreModule]UnityEngine.Debug::Log(object)IL_001b: ret} // end of method Test::.ctor.method private hidebysig instance void Start () cil managed {// Method begins at RVA 0x3656// Header size: 1// Code size: 1 (0x1).maxstack 8IL_0000: ret} // end of method Test::Start} // end of class MagicWorld.Test
如果沒(méi)有無(wú)參構(gòu)造函數(shù),有很多構(gòu)造函數(shù)的話(huà),上面的代碼會(huì)被寫(xiě)到指向父類(lèi)的構(gòu)造函數(shù)的那個(gè)構(gòu)造函數(shù)中,即:base()。
? ? ? ?如果是靜態(tài)字段在聲明時(shí)直接賦值則會(huì)在靜態(tài)構(gòu)造函數(shù)中執(zhí)行。?而靜態(tài)構(gòu)造函數(shù)會(huì)在程序集加載時(shí)由編譯器負(fù)責(zé)調(diào)用。
? ? ? ?因此,建議對(duì)于Mono腳本,初始化操作建議放到Awake或Start中去執(zhí)行。在編輯器模式下掛載腳步也是會(huì)執(zhí)行腳步的構(gòu)造函數(shù)的。對(duì)于靜態(tài)變量建議執(zhí)行懶初始化,即訪(fǎng)問(wèn)時(shí)為null時(shí)才執(zhí)行初始化,或者使用C#的Lazy<T>類(lèi)來(lái)完成懶初始化。
? ? ? ? 至少到目前Unity支持的C#9語(yǔ)法來(lái)看都是這樣的,以后就不清楚了。?