.NET 中的析构函数

Destructors in .NET

NET很久了,开始学C#。我想我几年前可能问过的一件事,得到了答案,但现在已经完全忘记了,因为它不是我暗中经常使用的东西是析构函数。在我学习 C# 的过程中,我阅读了一篇关于如何在 C# 中创建这些内容的文章,但它让我感到疑惑。假设我实例化了一个 class,它有一个指向另一个 class 的对象。

Class C1
{
  // Do something here
}

Class A
{
  C1 objObjectToClass1 = new C1();
}   

Class Main
{
   A objObjectToClassA = new A();
}

并且我将对象 objObjectToClassA 变为 null 因为我被引导相信这等同于 VB.NET 中的 object = nothing

objObectToClassA = null;

这个动作是否也会破坏objObjectToClass1

不是这样,不是。对象在符合收集条件后的某个时间会被垃圾收集器回收。这可能是在您清除对它的最后一次引用之后,但如果您在某一点之后不再需要该引用,则它可能已经存在。但一般来说,将存储实例的字段设置为 null 将有助于对象变得不再可访问并被回收。

通常您无法控制 GC 何时回收对象。您可以编写 finalizers ,这是在回收对象之前调用的方法,但如果您能提供帮助,我非常 not 推荐它.如果您需要一种可预测的方式来使对象释放它可能持有的任何资源(C++ 中的析构函数经常这样做),那么实现 IDisposable interface:

class C1 : IDisposable {
  public void Dispose() {
    // Do cleanup here
  }
}

这也使您能够在 using statement 中使用 class 的实例,它将在其块的末尾调用 Dispose

using (var c1 = new C1()) {
  // do stuf with c1 here
} // at this point c1.Dispose() is automatically called

垃圾收集器知道什么时候不再有对对象的引用,据我所知,它甚至会销毁仅被另一个引用的对象。

这意味着如果您取消引用 objObjectToClassA(将其设置为 null),如果不再有对任何一个对象的引用,那么这两个对象都将被销毁。简单地让它超出范围也足够了。

Destroy 这个词用错了,C#(据我所知)没有 C++ 意义上的析构函数。不再使用的对象被垃圾收集器收集/"destroyed"。

如果不保留对 objObjectToClass1 的其他引用,将 objObectToClassA 设置为 null

也可以收集 objObjectToClass1

实际上,是的,它也会摧毁 objectToClass1,但不会立即摧毁。在这种情况下,将变量设置为 null 意味着您的应用程序不再使用该对象,因此它有资格进行垃圾回收。简单地考虑一下(我敢肯定 GC 比这更聪明),一旦 objectToClassA 被收集,那么 objectToClass1 不再被引用,也会被收集。

Joey 关于 IDisposable 的评论绝对值得牢记;尽量不要考虑 C# 的终结器,因为您无法控制它们 运行 的时间。使用 IDisposable 将为您提供整理资源所需的控制权。