C#中对现有对象使用关键字'new'

36

我想知道当一个对象的引用被重新分配时(在C#中),会发生什么。例如:

Car c = new Car("Red Car");
c = new Car("Blue Car");

由于引用被重复使用,当'Red Car'失去其引用时,垃圾回收器是否会处理/处置它?还是需要实现一个单独的方法来处理'red car'?

我主要是想知道,因为我将要回收一个相对较大的对象,当它被重新创建时是否需要进行任何操作。

9个回答

36

在你的示例中,当 c 被分配给 Blue Car 时,cRed Car 实例将变得可回收。您不需要做任何操作。

查看这篇(虽然有些过时但仍然相关)关于.NET垃圾收集器的MSDN文章。http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

第一段话已经说明了一切:

在 Microsoft .NET 公共语言运行时环境中的垃圾收集器完全无需开发人员跟踪内存使用情况或知道何时释放内存。


根据所涉及的类型,调用Dispose可能是值得的。 - Phil Gan
1
假设没有对原始对象的其他引用(包括未注册的事件处理程序),那么你是正确的。 - Oded
1
@Phil:没错,但并不是很有帮助。如果存在Dispose,应该调用它,但这只是一个例外情况,并且仅在需要清理除内存以外的资源时才需要。 - user395760
该类通过Assemble.Load()加载插件,并将这些类/插件存储到数组中。我认为这被视为该对象的一部分。我不确定这是否会改变任何东西。 - Mike
7
@Richard: 我建议不要使用“disposed”这个词,因为它暗示了如果定义了IDisposable.Dispose方法,则会调用该方法,但事实并非如此。这会给人们带来误导。另外,我认为你引用的第一段也有点误导性。IDisposable也是GC过程中重要的一部分,因此,虽然该段落对于纯托管类型来说是正确的,但是对于那些看到你的答案的人来说,“完全免除”的说法是非常误导人的。 - Andy
@Dan,@Andy:我已经重新表述了我的答案。如果你们满意的话,可以更新或删除你们的评论,或者随意改进我的答案。 - Richard Ev

34
「由于参考被重用」,垃圾回收器会在失去引用后处理/处理“红色汽车”吗?你可能以错误的方式看待这个问题:
c [*] ----> [Car { Name = "Red Car" }]  // Car c = new Car("Red Car")

然后你的下一步:

c [*]       [Car { Name = "Red Car"  }] // No chain of references to this object
   \------> [Car { Name = "Blue Car" }] // c = new Car("Blue Car")

GC会在未来的某个时间收集任何没有与活动对象链相连的引用链的对象。对于大多数任务而言,只要使用托管数据,您不必担心大对象和小对象之间的区别。
对于大多数任务,只有在处理IDisposable时才需要关注确定性内存管理。只要遵循using块的最佳实践,通常就不会出现问题。

12
请注意,一个对象是否有“引用(reference)”并不是垃圾回收机制所检查的内容。垃圾回收机制检查的是从一个已知为活动状态的物体到该对象之间是否存在“引用路径(path of references)” 。一个对象可能会被某个东西所引用,但如果那个东西本身已经死亡,那么这个引用就不算数。 - Eric Lippert
谢谢,我在犹豫要包含多少内容(我回去加了一点关于“IDisposable”的内容)。我会更新以澄清。 - user7116

7
你创建一个新对象并将其引用分配给变量c。同时,先前的对象(“红色汽车”)现在不再被引用,可能会被垃圾回收。

6
如果没有其他对红色汽车的引用,它将在下一个循环中被垃圾回收器收集。您不需要任何额外的操作(除非它是一个具有流等需要被处理的类)。

5
垃圾回收器将在红色汽车不再被引用(不可达)时处理清理工作。您作为开发人员,通常不必担心在 .Net 中清理内存。
有三个需要提到的注意事项:
1. 它不会立即发生。垃圾回收将在其自行发生时进行。您无法预测它。
2. 如果该类型实现了 IDisposable 接口,您需要确保调用 .Dispose() 方法。使用 using 语句是实现这一点的好方法。
3. 您提到它是一个大对象。如果它超过 85000 字节,它将存储在一个称为大对象堆的地方,该地方具有非常不同的垃圾回收规则。允许这种类型的对象频繁地进行回收可能会导致问题。

0

垃圾收集器将负责处理汽车对象的处理


0

垃圾回收器将会回收你的红色汽车对象并进行处理。

如果你有需要在原始对象不再使用时释放的资源,你可以调用自定义析构函数或实现IDisposable接口。


0

如果 Car 持有一些本地资源,您需要实现 IDisposable 并在重用变量之前正确处理它。


0

我认为你应该实现IDispose接口来清理非托管资源

public class car : IDispose 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接