Unity3D中的C#脚本环境(在Mono下运行)在销毁对象时有一个很好的行为。所有指向被破坏对象的引用都会自动为空:
GameObject ref1 = (GameObject)Instantiate(obj);
GameObject ref2 = ref1;
if (ref1 != null)
Debug.Log("ref1 is not null");
DestroyImmediate(ref1);
if (ref1 == null)
Debug.Log("ref1 is null");
if (ref2 == null)
Debug.Log("ref2 is null");
输出:
ref1 is not null
ref1 is null
ref2 is null
关于如何实现这一点的任何想法?
由于
答案 0 :(得分:3)
也许等于运算符被覆盖了?这可以解释你的评论:“只要知道如果ref1和ref2不是GameObject而是System.Object,那么它就行不通。”
答案 1 :(得分:2)
Unity3D(ab)可能会使用运算符重载+某种内部标记,例如bool isDeleted;
,以便在isDeleted
中将true
设置为DestroyImmediate
时函数然后针对null
的等式测试产生true
。
答案 2 :(得分:1)
您不能在C#中通过值参数调用来执行此操作。您还必须使用ref
参数,这些参数在呼叫站点也需要ref
个关键字。
事实上,在.NET中没有可用但可破坏(即解除分配)的托管对象的有用概念(好吧,忽略WeakReference
并不真正计算)。对象无法访问或无法销毁。
答案 3 :(得分:0)
这在“常规”.NET中是不可能的,而不是CLR如何工作。
答案 4 :(得分:0)
虽然这是一项有趣的学术挑战,但从技术角度来看并不值得追求。你从错误的角度看待这个--CLR为你管理对象的生命周期。将所有“变量”设置为null的唯一方法是使用“ref”参数修饰符将所有变量传递给destroy方法。除非你计划在一个方法中编写整个程序,否则你就会咆哮错误的树。正确结构化的类和方法将确保超出范围的变量“被淘汰”,释放垃圾收集的目标对象。
答案 5 :(得分:0)
您可以添加一个中间类(代理)来保存对实际类的引用。
你的所有引用都是这个新的GameObjectProxy。这将提供与GameObject相同的API,并将其上的任何调用转发给基础GameObject对象。
GameObjectProxy还提供额外的方法 - 销毁底层GameObject,并查询GameObject是否为null。 (如果你想成为邪恶的话,这些可能会被构建到operator =和operator ==)
请记住,这种方法可能会降低性能,因为每次调用GameObject都必须通过代理重定向。它也有点邪恶 - 它会让那些期望他们的引用行为“正常”的程序员感到困惑。