0

Quick question.

Consider this code

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?
    }
}

Now, when I run Test1 would the old Tile's finalizer be called? What about Test2?

4

3 回答 3

3

答案是不。

直到垃圾收集器决定它想要的对象才最终确定。在这一点上,你没有做任何远程像 C++ 的delete. 您只是分配新的内存部分并更改指针(大致)。

如评论中所述:终结器(C#)和析构器(C++)不一样。

于 2013-06-17T04:28:46.200 回答
1

C# 中的析构函数(正确名称是“终结器”)的问题是,您永远不知道它们何时会被调用。只要对象超出范围,就可以调用它。它可以在您的程序结束时调用。在某些情况下,它们甚至可能根本不被调用。这完全取决于垃圾收集器。

所以不要为你的系统逻辑使用析构函数。根本没有多少情况应该使用析构函数。

于 2013-06-17T04:29:13.720 回答
0

您的代码不完整。如果它是完整的,引用对象将像 一样被链接CollisionHandler->Collision->Tile,所以你的被忽略的对象Tile永远不会被垃圾收集器收集。

.NET GC 是非确定性的,所以如果你正在寻找类似自动管理的确定性析构函数的东西,那么你就不走运了。.NET 框架为IDispose首选确定性清理的情况提供接口,例如文件 I/O 操作,但消费者必须意识到这一点并Dispose显式调用或使用语言的特性(如usingC# 中的关键字)。

于 2013-06-17T04:46:41.273 回答