MonoBehavior子类返回null仍然可以使用

这篇文章其实是 记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);
    }
}

输出:
mono

首先是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:
反汇编是指从机器语言到汇编语言
反编译是指从机器语言到高级语言

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值