Unity/C# 空引用异常不存在,但应该存在
Unity/C# null reference exception isn't present, but should be
程序落到这个分支了还没有暗恋,很意外。对象被销毁并为空,但所有数据仍然相同。据我了解,它应该因空引用异常而崩溃。我是否遗漏了一些关于 null 在 c# 中如何工作的一般信息,或者我在 unity/dotnet 中遇到了一些已知错误?
if (begining == null)
{
print(begining.marked);
foreach (var near in begining.nears)
{
print(near);
}
print(begining!.distance);
print(begining.nears_amount);
print(begining.prev);
}
开头是节点类型的对象:
public class Node : MonoBehaviour
{
public int nears_amount = 3;
public readonly HashSet<Node> nears = new HashSet<Node>();
public float distance = Single.PositiveInfinity;
public Node? prev = null;
public bool marked = false;
public void connect(Node another);
private void OnDrawGizmos();
public void disconnect_all();
private void OnMouseOver();
public static bool BFS(Node start, Node seeked);
public static List<Node> Dijkstra(Node start, int depth = -1);
public static List<Node> DFS(Node current, int depth);
}
调试器:
长话短说:一般来说,对于从 UnityEngine.Object
继承的事物,在检查是否存在
时宁愿使用 bool
operator
if (begining)
{
print(begining.marked);
foreach (var near in begining.nears)
{
print(near);
}
print(begining.distance);
print(begining.nears_amount);
print(begining.prev);
}
请注意,对于从 UnityEngine.Object
.
继承的任何内容,Unity 都有一个 Custom ==
implementation (see also further explanation here)
这个习俗==
主要是基于
static bool CompareBaseObjects(UnityEngine.Object lhs, UnityEngine.Object rhs)
{
bool lhsNull = ((object)lhs) == null;
bool rhsNull = ((object)rhs) == null;
if (rhsNull && lhsNull) return true;
if (rhsNull) return !IsNativeObjectAlive(lhs);
if (lhsNull) return !IsNativeObjectAlive(rhs);
return lhs.m_InstanceID == rhs.m_InstanceID;
}
虽然基础 System.Object
(= object
) 实际上可能 而不是 在 c#
层上 null
,这custom ==
额外检查 c++
层上的底层实例是否存在或被销毁 (IsNativeObjectAlive
).
请注意 Unity 如何不显示 NullReferenceException
而是显示自定义 MissingReferenceException
,表明此 System.Object
实际上不是真正的 null
,而是 Unity 运算符==
returns true
对于 null
,即使 System.Object
仍然存在。
一旦您销毁了一个对象,然后尝试在同一帧中访问它(或者最好在 GC 收集该实例并使这个 System.Object
实际上 null
之前说得更好),就会发生这种情况。 =50=]
所以一般来说:不要使用 == null
而是使用 bool
运算符来检查是否存在(尽管 Unity API 经常不幸地使用 == null
本身) .
更进一步:从不对UnityEngine.Objetc
使用?.
, ??
/ ??=
or !.
运算符,因为它们也在底层System.Object
上运行并忽略自定义==
和 Equals
实施 UnityEngine.Object
!
程序落到这个分支了还没有暗恋,很意外。对象被销毁并为空,但所有数据仍然相同。据我了解,它应该因空引用异常而崩溃。我是否遗漏了一些关于 null 在 c# 中如何工作的一般信息,或者我在 unity/dotnet 中遇到了一些已知错误?
if (begining == null)
{
print(begining.marked);
foreach (var near in begining.nears)
{
print(near);
}
print(begining!.distance);
print(begining.nears_amount);
print(begining.prev);
}
开头是节点类型的对象:
public class Node : MonoBehaviour
{
public int nears_amount = 3;
public readonly HashSet<Node> nears = new HashSet<Node>();
public float distance = Single.PositiveInfinity;
public Node? prev = null;
public bool marked = false;
public void connect(Node another);
private void OnDrawGizmos();
public void disconnect_all();
private void OnMouseOver();
public static bool BFS(Node start, Node seeked);
public static List<Node> Dijkstra(Node start, int depth = -1);
public static List<Node> DFS(Node current, int depth);
}
调试器:
长话短说:一般来说,对于从 UnityEngine.Object
继承的事物,在检查是否存在
bool
operator
if (begining)
{
print(begining.marked);
foreach (var near in begining.nears)
{
print(near);
}
print(begining.distance);
print(begining.nears_amount);
print(begining.prev);
}
请注意,对于从 UnityEngine.Object
.
==
implementation (see also further explanation here)
这个习俗==
主要是基于
static bool CompareBaseObjects(UnityEngine.Object lhs, UnityEngine.Object rhs) { bool lhsNull = ((object)lhs) == null; bool rhsNull = ((object)rhs) == null; if (rhsNull && lhsNull) return true; if (rhsNull) return !IsNativeObjectAlive(lhs); if (lhsNull) return !IsNativeObjectAlive(rhs); return lhs.m_InstanceID == rhs.m_InstanceID; }
虽然基础 System.Object
(= object
) 实际上可能 而不是 在 c#
层上 null
,这custom ==
额外检查 c++
层上的底层实例是否存在或被销毁 (IsNativeObjectAlive
).
请注意 Unity 如何不显示 NullReferenceException
而是显示自定义 MissingReferenceException
,表明此 System.Object
实际上不是真正的 null
,而是 Unity 运算符==
returns true
对于 null
,即使 System.Object
仍然存在。
一旦您销毁了一个对象,然后尝试在同一帧中访问它(或者最好在 GC 收集该实例并使这个 System.Object
实际上 null
之前说得更好),就会发生这种情况。 =50=]
所以一般来说:不要使用 == null
而是使用 bool
运算符来检查是否存在(尽管 Unity API 经常不幸地使用 == null
本身) .
更进一步:从不对UnityEngine.Objetc
使用?.
, ??
/ ??=
or !.
运算符,因为它们也在底层System.Object
上运行并忽略自定义==
和 Equals
实施 UnityEngine.Object
!