在标准.NET 4.6编译器中,以下if语句不合法,您将收到编译器错误:CS0029无法将类型'UserQuery.TestClass'隐式转换为'bool'。这一切都很好,我理解这一点。
void Main()
{
TestClass foo = new TestClass();
if(foo)
{
"Huh. Who knew?".Dump();
}
}
public class TestClass : Object
{
}
然而,在Unity3d中,这段代码是完全合法的,我看过几个例子,甚至鼓励这种Javascript风格的空检查。
这里发生了什么,是否可以在.NET中的非Unity3d工作中利用这一点?
以下是Unity3D中合法代码的示例:
using UnityEngine;
public class SampleIfBehavior : MonoBehaviour
{
// Use this for initialization
void Start ()
{
var obj = new SampleIfBehavior();
if (obj)
{
Console.Write("It wasn't null.");
}
}
}
情节变浓!如果我尝试比较一个不是从单声道行为派生的对象,我会得到预期的编译器警告。
public class TestClass
{
}
void Start ()
{
var obj2 = new TestClass();
if (obj2) // cast from TestClass to bool compiler error
{
}
}
感谢Programmer,我一直在挖掘Unity3D的Object(我忽略了它,因为我错误地认为它是.NET的实际对象。)
好奇的相关代码(在UnityEngine.Object中):
public static implicit operator bool(Object exists)
{
return !Object.CompareBaseObjects(exists, (Object) null);
}
public static bool operator ==(Object x, Object y)
{
return Object.CompareBaseObjects(x, y);
}
public static bool operator !=(Object x, Object y)
{
return !Object.CompareBaseObjects(x, y);
}
答案 0 :(得分:11)
if (obj)
仅在Unity中合法,因为Unity中存在隐式运算符重载。我相信这是在MonoBehaviour
或UnityEngine.Object
类中完成的。
它看起来像这样:
public static implicit operator bool($classname$ other){
return other != null;
}
Unity计划删除此功能,但决定反对它,因为它会破坏每个Unity代码。您可以阅读有关此here的更多信息。
此功能非常糟糕的一面是它无法在编辑器中使用Null-Coalescing运算符功能。好的一面是它简化了对null
的检查
答案 1 :(得分:0)
我阅读了许多有关此主题的文章,其中包括 @Programmer 和other on stackoverflow提到的内容。可能出现问题的根源是明确的,尤其是在删除GameObject的情况下(例如),并在使用"!=null" or "!((bool)GameObject)"
测试其存在之后。
我决定对此问题进行简单检查(Unity 2019.4.14 LTS):
一个将要删除的GameObject具有脚本
public class CheckDestroy : MonoBehaviour
{
public OnGUITest linkToMangerObject;
private void OnMouseDown()
{
linkToMangerObject.InitCount();
Destroy(gameObject);
}
}
其他GameObject,用于测试已删除对象的存在:
public class OnGUITest : MonoBehaviour
{
private int externalCount;
private bool flagObjectDeleted = false;
public GameObject deletedObject;
void OnGUI()
{
if (flagObjectDeleted)
if (deletedObject)
//if (deletedObject != null)
externalCount++;
else
print($"Detected the object deleted, count={externalCount}");
}
public void InitCount()
{
externalCount = 0;
flagObjectDeleted = true;
}
}
结果是,验证对象立即检测到其他对象的破坏。 这是一个综合测试,具有最大程度的简单场景,并且对CPU / Mem和垃圾回收的负载最小。
也许在实际情况下(在实际负载下)它将以不同的方式工作,或者可能是更改了本机代码-附加检查了吗?