这篇文章其实是 记MonoBehavior与单例模式碰撞的火花的后续篇。可以读一下,可以更好的理解本文。
众所周知,继承MonoBehavior的子类是不能使用new来实例化的。但是如果我们强行new一下呢?
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using System;
public class henfan : MonoBehaviour {
void Start () {
MonoChild mono = new MonoChild();
if (mono == null)
{
Debug.Log("mono == null");
}
mono.words = "hahaha";
mono.Foo();
}
}
class MonoChild : MonoBehaviour
{
public string words = "hello Mono";
public int count;
public void Foo()
{
Debug.Log(words);
}
}
输出:
首先是warning警告我们不能用new实例化继承了MonoBehaviour的子类。然后mono==null确实成立。但是,如果设置mono.words以及调用mono.Foo()都没有问题。
嘴上说没有,实际上已经实例化、分配内存了??
在判断mono==null后添加以下代码:
unsafe
{
fixed (int* p = &mono.count)
{
Debug.Log("mono count address: " + (int)p);
}
}
确确实实在为mono分配了内存~
结论:
强行用new实例化MonoBehavior子类:
MonoChild mono = new MonoChild();
1. mono==null 为true
2. 进行了内存分配,可以“不合法”地正常使用mono
后续
学习了一下反汇编及IL代码的阅读,用ILSpy反汇编后:
.method private hidebysig
instance void Start () cil managed
{
// Method begins at RVA 0x213c
// Code size 32 (0x20)
.maxstack 2
.locals init (
[0] class MonoChild
)
IL_0000: nop
IL_0001: newobj instance void MonoChild::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldnull
IL_0009: call bool [UnityEngine.CoreModule]UnityEngine.Object::op_Equality(class [UnityEngine.CoreModule]UnityEngine.Object, class [UnityEngine.CoreModule]UnityEngine.Object)
IL_000e: brfalse IL_001f
IL_0013: nop
IL_0014: ldstr "mono == null"
IL_0019: call void [UnityEngine.CoreModule]UnityEngine.Debug::Log(object)
IL_001e: nop
IL_001f: ret
} // end of method henfan::Start
可以看到IL_0001确实进行了实例化,再次证实了我们的之前的结论。
ps:
反汇编是指从机器语言到汇编语言
反编译是指从机器语言到高级语言