【问题标题】:What happens to an object when it's reference is reassigned?当对象的引用被重新分配时会发生什么?
【发布时间】:2016-04-29 02:30:00
【问题描述】:

当一个对象被实例化时:

Foo objFoo = new Foo();

当它的引用 objFoo 被重新分配时,它的内存分配会发生什么?

objFoo = new Foo();

赋值为null时呢?

objFoo = null

【问题讨论】:

标签: c# .net class object memory


【解决方案1】:

当我们将另一个实例分配给对象时,当前使用的内存会发生什么。

objFoo 是一个变量,而不是一个对象。

objFoo = new Foo(); 创建一个新对象 (new Foo()) 并将其分配给 objFoo 变量。

如果您调用 objFoo = new Foo(); 并且没有其他变量引用同一个旧对象,则旧对象将有资格被垃圾回收。

垃圾回收不会立即发生,但当它发生时,它会释放旧对象使用的内存。

查看this MSDN reference 了解有关垃圾收集的更多信息。

当 null 分配给对象时,内存会发生什么。即,objFoo = null

和我之前的笔记一样。如果没有其他变量引用旧对象,则该对象将有资格进行垃圾回收。

在第一种情况下,我可以访问新对象,而在第二种情况下,访问值会给我空引用异常。

变量 objFoo 现在没有引用任何东西,这就是为什么当您尝试访问它所引用的对象时会出现异常。

【讨论】:

  • 虽然不适用于示例类,但重要的是要注意垃圾收集只会自动处理托管内存,如果您的类包含非托管内存(句柄、流、打开文件等),那么您将需要实现IDisposable 接口以正确释放内存。
  • @NathanC ...并尝试将此类资源包含在using 语句中,隐式调用Dispose
【解决方案2】:

当您删除对对象的最后一个引用时(在这种情况下,通过将变量设置为 either 一个新对象或null,它基本上是相同的)它被标记为可用于被垃圾收集。

这并不意味着内存会立即被释放(尽管这可能会发生),所以如果您有一些非托管方式访问内存,它仍然会显示为“存在”一段时间。

在某个时间点(您无法确定)内存被释放。

如果您有其他变量/列表等引用该对象,则它不符合垃圾回收条件。

【讨论】:

    【解决方案3】:

    在开始时,objFoo 包含对内存中第一个对象地址的引用。当您创建并分配第二个对象 new Foo() 时,它会在内存中创建一个新对象并将新引用放入 objFoo 中。旧对象,如果不再在代码中的其他地方引用,则成为垃圾收集器的候选对象。您不会“覆盖”内存,您只需为新对象使用另一个内存范围。

    对于您的第二点,几乎相同。当您将空引用分配给 objFoo 变量时,如果没有其他变量引用它,前一个对象将成为 GC 的候选对象。由于您的变量实际上确实引用了一个空值而不是内存中引用的有效 Foo 对象,因此您会收到此错误。

    在任何情况下,你都不知道 GC 什么时候会释放内存。

    【讨论】:

      猜你喜欢
      • 2022-06-27
      • 1970-01-01
      • 1970-01-01
      • 2016-01-20
      • 1970-01-01
      • 2015-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多