如何在C#中删除一个数组?

33

如果这是一个显而易见的问题,我很抱歉,但无论是谷歌还是在这里搜索都没有得到答案。

是否有一种方法可以完全删除一个数组?

我想要相反的效果:删除 int[] array = new int[5]


1
@ShuggyCoUk 嗯,实际上我正在上一门大学课程,并填补教授留给我们的(不幸的)空白,这些空白在文献中没有涵盖的问题。 我想提问的艺术比学习答案更重要,所以当我找不到答案时,我会继续提问。 - Patrik Björklund
2
@bigge 那么,2009年的问题有更多的赞和答案,它怎么成了今年7月发布的那个问题的重复? - Anthony Neace
11个回答

57

假设你调用了:

 void Foo(){
     int[] a = new int[5];
 }

在C#中,无法取消定义变量a的方式。这意味着即使将a设置为null,在Foo中仍将定义a。 但是,在Foo结束时,a将超出范围。这意味着没有代码可以引用它,并且垃圾回收器会在下一次运行时自动释放内存,这可能需要很长时间。


6
谢谢你提供明确的答案,这样我就不用在谷歌上花太长时间查找了。 - Patrik Björklund
我知道这是一个旧的帖子,但我希望有人能帮忙。我观察到在托管的.Net代码中,直到应用程序关闭时,GC并没有做好工作。当数组或对象的内存分配和处理非常频繁和重复时,即使正确使用(){}块,内存也不会被释放。我观察到它在任务管理器中不断增加,而我坐在椅子边想知道如何在崩溃之前控制它。这里有任何未记录的秘密吗? - Pradeep Puranik
@Pradeep Puranik,我认为你提出一个新问题会更有好运。 - RossFabricant

18

您只需要让它超出范围,并等待GC找到它;这可能不会立即发生(实际上,几乎肯定不会)。如果您有一个长期存在的对象上的字段(将保持在范围内),那么可以将其设置为null,这可能有所帮助。

您可以影响GC更早地进行收集(不仅是您的对象:所有符合条件的对象),但您应该很少甚至从不这样做。我只在测试环境中使用它;但:

GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); // DON'T DO THIS!!!

更多关于GC.Collect的信息:


6

您应该阅读Chris Brumme关于这个主题的文章;前几段应该解释了情况。

任何建议“将变量赋值为null”的人都应该特别注意其中所说的:

即使在使用后添加“aC = null;”,JIT也可以将此赋值视为死代码并将其消除。


链接已失效 :( - garfbradaz

5
没有必要删除数组,垃圾回收器会处理它。
简单地说:
当你的内存用完时,垃圾回收器会启动,停止你的代码并遍历内存中的所有活动对象。 “活动”意味着在堆栈、寄存器、静态引用和一些其他被称为“GC Roots”的东西中有一些引用。当它遍历它们时,它会注意到它们是活动的。
如果您的数组不再活动,那么没有任何方式可以访问它了(这就确定了活性),因此它占用的内存将可供重用。
如果一个引用持有的内存比预期时间更长,或者它持有一个需要立即使用的大块内存,那么将引用分配为空可能有原因,但这很容易适得其反,实际上会使数组的生命周期更长。如果包含实例的生命周期比它包含的数组长得多,那么实例变量比堆栈变量更适合进行此优化。
明确一点,作为初学者,你不应该考虑这种事情,让垃圾回收器完成它的工作,并且只有在以下情况下才尝试帮助它: 1.知道你需要做什么 2.知道如何做 3.知道如何检查你是否做对了。

3
数组等于null就足够了,不需要使用GC.Collect。在引用null之前,您可以通过Console.WriteLine(GC.GetTotalMemory)检查内存,然后再次检查。

3

数组为null,但我认为如果您了解.NET内存管理模型,就可以充分理解为什么这样做是一个好主意。


2
你可能应该被点个踩,因为这是错误的。请阅读有关将引用分配为 null 的部分,这是死代码,JIT 可以在此处消除:http://blogs.msdn.com/cbrumme/archive/2003/04/19/51365.aspx - Greg Beech
1
(顺便说一句,我没有投反对票,因为阅读更多关于 .net 内存模型的建议是一个好主意) - Greg Beech
1
好的,你说得对,我应该明确表明我更多是指“我想要与 int[] array = new int[5] 相反的东西”这个陈述,而不是实际的问题。 - Trap

3

如果你不理解其他回答中提到的术语,GC是垃圾收集器的缩写。像C#这样具有自动内存管理功能的语言可以让你专注于完成任务,而不必担心你正在创建什么以及何时删除它。GC会定期浏览你创建的所有对象,并查看它们是否有任何引用。如果没有,这意味着你无法对它们做任何事情,因此最好将它们删除,系统也确实这样做了。

更多详情,请参见http://en.wikipedia.org/wiki/Garbage_collection_(computer_science)


1

最接近的方法就是等待它超出作用域或将其设置为null。

它不会立即删除数组,但在您放弃对数组的所有引用后,垃圾收集器(GC)将及时删除它...


0
在C++中,可以使用delete关键字。原始评论和其他评论中都提到了它。编辑历史显示了这一点。即使其他人不理解为什么,这是可行的(尽管是侧面答案)。我之所以这样说,是因为如果一个人理解超过一种语言,他们可以使用它来找到自己的优雅解决方案。
在.NET/MSIL中,你有删除关键字,但它被称为variablename.Dispose()。我提供这个是因为它会移除所有对变量的引用,并将其推入准备好进行垃圾回收的状态。另一个选择是将变量设置为null,因为这会将变量保留为一个类型化对象,但释放它所持有的内容以供垃圾回收使用,以便稍后重新分配。
原始评论/答案:
C#的垃圾回收功能非常出色,但有时您确实需要从内存中删除一个变量并创建一个新实例,而不让程序的其他部分保持它的存活状态。通过将数组指向新的内存块,例如:可以将数组中保存的现有内存块潜在地放置到GC状态下。
aMyArray = new int[];

然而,我发现这种方式的主要问题是,您真的不希望浪费大量内存,然后在操作系统发疯启动垃圾收集器时一切都停滞不前。考虑到C#现在是一种主流语言,并且被广泛用于各种应用程序,包括编写游戏... 如果C#在这方面不像ActionScript/FLASH那样,那将是非常好的。


0
你可以在 if (true) {} 语句中声明和初始化数组,在 if 语句之外(在其后)该数组变量将不可访问,因此它将被删除。

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