Unity的==与空并运算符(?.)
Unity.Object使用==与?.的区别
众所周知,C#的判空有两种:==与?.(空并运算符),之前因为没有深入了解两种判空的在Uniyt.Object中的差别,开发的时候更是想到谁就用谁,造成了一些Crash,下面详细讲解两者的区别。
Unity.Object使用?.

如上图代码和结果所示,在使用GameObject.DestroyImmediate函数当帧立即销毁之后,打印name还是执行了并且报空,说明?.无法正确的判断Unity.Object为空。
Unity.Object使用==

如上图代码和结果所示,在使用==判断时,成功判断了对象为空。
差别的原因
在解释之前,补充一段关于Unity.Object的知识。Unity运行时是C++的,所有的对象都在C++层管理,在C#层只是有一个引用对象指向C++对象。所以,就有一种情况,就是C++层的对象被销毁了,但是C#层的对象还存在,导致判空出错。
了解了这个知识点,下面开始探究问题所在。以下是Unity重载==运算符的源码:
上面的方法用来比较两个 UnityEngine.Object 对象是否相等,lhs 和 rhs 分别代表操作符两边的参数:
1.若两边参数在 CLR 层均为 null,判定相等;
2.若右边参数在 CLR 层为 null,左边不为 null,根据左边参数 CLR 层所在对象对应的底层原生对象是否 Alive 返回比较结果;
3.若左边参数在 CLR 层为 null,右边不为 null,根据右边参数 CLR 层所在对象对应的底层原生对象是否 Alive 返回比较结果;
4.否则左右两边对象在 CLR 层对象均不为 null,比较它们的 m_InstanceID 是否相等。
在上面的测试代码中,?.是没有被Unity重载的,他仅仅只是判断对象在C#层是否为空;而==不仅判断了C#层,同时也判断了C++层的引用,最终导致了两者结果的不同。
Unity.Object与System.Object判空的性能差异
因为Unity.Object重载了==,并且需要判断C++层的引用,所以性能一定要差于System.Object。下面是我测试代码,生成1w个Object,遍历判断是否为空,最后得出的结果Unity.Object花了0.36ms,System.Object花了0.29ms,性能差异大概是1.2倍,所以要避免在Update和轮询中对Unity.Object判空!




