将对象排除在范围之外

本文关键字:范围 对象 排除 | 更新日期: 2023-09-27 18:18:35

快速提问

考虑以下代码

public class Tile
{
    public Collision Collision;
    public Tile()
    {
        Collision = new Collision(this);
    }
    public ~Tile()
    {
        CollisionHandler.Remove(Collision);
    }
}
public class Collision
{
    public Collision()
    {
        CollisionHandler.Add(this);
    }
}
public class Main
{
    public Main()
    {
        Test1();
        Test2();
    }
    public void Test1()
    {
        Tile[,] tiles = new Tile[20,20];
        tiles[0,0] = new Tile();
        tiles[0,0] = new Tile();
        //Would calling the above call the old Tile's destructor?
    }
    public void Test2()
    {
        Tile[,] tiles = new Tile[20,20];
        tiles[0,0] = new Tile();
        Tile t = new Tile();
        tiles[0,0] = t
        //Would calling the above call the old Tile's destructor?
    }
}

现在,当我运行Test1时,旧的Tile的终结器被称为?Test2呢?

将对象排除在范围之外

答案是否定的

对象直到垃圾收集器决定它想要结束时才结束。在这一点上,您没有做任何类似于c++的delete的远程操作。你只是分配了一部分新的内存,并改变了一个指针(大致)。

如注释所述:终结器(c#)和析构器(c++)是不一样的

c#中的析构函数(正确的名称是"finalizer ")就是你永远不知道什么时候会调用它们。只要对象超出作用域,就可以调用它。它可以在程序结束时调用。在某些情况下,它们甚至可能根本不被调用。这完全取决于垃圾收集器。

所以不要对系统逻辑使用析构函数。并不是所有的情况都应该使用析构函数

您的代码不完整。如果它是完整的,那么引用对象将像CollisionHandler->Collision->Tile一样被链接起来,因此您忽略的Tile无论如何都不会被垃圾收集器收集。

. net GC是非确定性的,所以如果你正在寻找像自动管理的确定性析构函数这样的东西,那么你就不走运了。net框架提供了IDispose接口,用于优先考虑确定性清理的情况,例如文件I/O操作,但消费者必须意识到这一点,并显式调用Dispose或使用语言的功能,如c#中的using关键字。