C#自动引用赋值 - 使引用为null

时间:2010-01-24 21:35:20

标签: c# reference variable-assignment

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

关于如何实现这一点的任何想法?

由于

6 个答案:

答案 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都必须通过代理重定向。它也有点邪恶 - 它会让那些期望他们的引用行为“正常”的程序员感到困惑。