如何在C# XNA中调用析构函数

7

我有一个对象,只想在某个事件上销毁它。如何在XNA中调用析构函数?

7个回答

6
将对象设置为null,垃圾收集器将在下一次运行时回收它。
顺便提一下,如果该对象是您经常创建的内容(敌人、子弹等),则可能希望使用而不是删除该对象。这意味着对象被回收利用,因此垃圾收集器调用较少,从而提高性能。

2
天啊,在.NET中,那是你最不想做的事情。 - Nick Berardi
1
@Nick Berardi - 你能解释一下为什么吗?因为它似乎值得被踩。为什么将少量对象引用到null并推荐使用pool是你最不想做的事情?@Nasgharet - 有什么问题吗?另外,smokeList听起来像是一个粒子系统。如果是这种情况,你应该对所有对象使用池而不是null - keyboardP
2
@Nashgharet,你的代码无法正常工作的原因是事件处理程序一直保持着对象的作用域,因为该事件从未与对象解绑。在对象被回收之前,你需要调用 -= 来移除该事件。 - Nick Berardi
2
@Nick Berardi - 不,它不会立即影响内存。问题是在游戏中销毁对象(即失去引用)。IDisposable模式当然适用于删除,但OP并不关心内存删除,而是销毁对象。在实时游戏中强制GC是不负责任的(尤其是在XBox/WP7上),而“池化”仍然比“处理”(常见对象)更好。从内存角度来看,没有必要将其设置为“null”,但在尝试从游戏中删除敌人时,这有助于解决问题。子弹何时会自动超出范围? - keyboardP
1
@keyboardP,你所说的是设计考虑而不是内存清理,第二个问题是他举的例子在gameTime对象被释放之前永远不会释放dym对象,因为事件处理程序创建了强引用。这是事件驱动模型常见的问题,所以即使你设置为null,它也不会在gameTime被释放之前被释放。 - Nick Berardi
显示剩余5条评论

3

除了仅使用Dispose之外,您可以遵循可释放模式,以便在需要时释放对象,但如果超出范围,则由GC处理。 - fire.eagle

1

将此对象的引用设置为null


0

将对象设置为null后,如果您希望出于某种原因立即收集该对象,请调用GC.Collect()


不好的通用建议。调用GC.Collect不能保证它会立即进行垃圾回收,而且可能会导致比值得解决的问题更多的问题。 - Gregory A Beamer
1
来自 MSDN 上的 @Gregory A Beamer 关于 GC.Collect 的解释:_"强制立即回收所有代的垃圾。"_ 当然,是否应该调用 GC.Collect 取决于具体情况。例如,如果一个对象消耗了大量需要尽快释放的内存,那么使用 GC.Collect 是有帮助的。 - Centro
1
让我修改一下我匆忙表述的话。GC不能保证清理任何对象。我喜欢Rico关于垃圾回收的规则:http://blogs.msdn.com/b/ricom/archive/2004/11/29/271829.aspx - Gregory A Beamer

0
什么样的对象?如果是一个可释放的/IDisposable,你应该调用object.Dispose()。 否则,你可以只使用object=null,它会自动“清理”。这不是你正在工作的C语言 ;) 如果你的“对象”实际上是一个复杂的类或者包含更多对象的东西,你可能需要考虑将其制作成一个IDisposable类。

0
如果对象持有任何非托管资源,则实现IDisposable(并在使用后使用using或调用Dispose())。
如果不持有非托管资源,则垃圾回收器将在没有更多的引用时,"在某个时间点" 去回收该对象。
GC.Collect() 将使垃圾回收器进行回收,如果没有引用它,它将 "销毁" 您的对象。这不是一个很好的主意,因为它会影响性能(这需要一定的时间,并将其他对象提升到更高的代数,使它们在被回收之前在内存中保留更长的时间)。
您为什么需要在特定的固定时间销毁对象呢?

0

如果您正在处理清理工作,您需要调用GC.SuppressFinalize()。通常情况下,您会在IDisposable类中使用GC.SuppressFinalize()。请参阅此代码示例以了解IDisposable的常见用法:

http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx

如果你真的需要立即进行垃圾回收:

var myObj = new MyObject();

// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue 
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(myObj);

但是我要提醒你,你应该让对象超出范围,并让GC自然地收集对象。只要你不试图做它的工作,.NET运行时非常有效地管理内存。

编辑

在查看评论后,我发现你忘记了一个重要的信息,即你正在将问题对象绑定到其他对象的方法中。这意味着你尝试完成的对象不会完成,直到用于观察事件的方法完成,从而在内存中保留大量额外的对象。

为了打破这个强引用,你可以使用一个叫做WeakReference的对象。或者使用lambda表达式来打破强引用。

参见这个使用WeakReference的示例http://msdn.microsoft.com/en-us/library/system.weakreference.aspx

或者你可以像这样做:

dym.cas += (x, y, z) => gameTime.ElapsedGameTime(x,y,z);

替代

dym.cas += gameTime.ElapsedGameTime;

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