“你的”是什么;“当心”;关于在编写.NET代码时避免内存泄漏的列表?

“你的”是什么;“当心”;关于在编写.NET代码时避免内存泄漏的列表?,.net,memory-leaks,.net,Memory Leaks,在编写数千行.NET代码时,为了避免内存泄漏,您会牢记什么? 我非常喜欢预防过度检查,关于这一点,有一个著名的例子,它使用“StringBuilder”来组合字符串,而不是“String1+String2”,那么从您的编码经验中还有什么 提前感谢您分享您的想法。每个DataTable.NewRow()都必须有一个匹配的DaraTable.Rows.Add(…)。请确保始终处理IDisposable对象。此外,尝试始终使用“using(…)”块来声明一次性对象。使用后将根引用设置为null 更多信

在编写数千行.NET代码时,为了避免内存泄漏,您会牢记什么? 我非常喜欢预防过度检查,关于这一点,有一个著名的例子,它使用“StringBuilder”来组合字符串,而不是“String1+String2”,那么从您的编码经验中还有什么


提前感谢您分享您的想法。

每个DataTable.NewRow()都必须有一个匹配的DaraTable.Rows.Add(…)。

请确保始终处理IDisposable对象。此外,尝试始终使用“using(…)”块来声明一次性对象。

使用后将根引用设置为null

更多信息:
如果我们忘记清空根引用,GC将无法尽快有效地释放内存,从而导致应用程序占用更大的内存。问题可能很微妙,例如,在进行远程调用(如数据库查询或对Web服务的调用)之前创建大型临时对象图的方法。如果在远程调用期间发生垃圾收集,则整个图被标记为可访问且不被收集。这会变得更加昂贵,因为在收藏中幸存下来的物品会被提升到下一代,这可能会导致中年危机。

尽可能意识到你所做的每件事的复杂性,并考虑每种情况,而不是依赖教条。例如,还要注意:)

在可能的情况下,尝试流化数据而不是缓冲数据-在这里,当涉及到LINQ to对象时,您需要小心,了解哪些运算符缓冲哪些流(以及哪些运算符使用不同的序列同时缓冲和缓冲)


(这两种情况都不是真正的内存“泄漏”——但我想的是可以快速使用比预期更多内存的地方。)

事件。总是取消订阅事件,这是.NET提供泄漏最多的一个功能

订阅活动意味着“在你活着的时候通知我并抱住我”,而不是“在我活着的时候通知我”。未能取消订阅事件通常会导致大量挂起的对象,尤其是在UI中

something.someEvent += new EventHandler(memoryhog.someMethod);
[...]
something.someEvent += new EventHandler(memoryhog.someMethod);
[...]
something.someEvent -= new EventHandler(memoryhog.someMethod);
如果未从对象中解除所有事件处理程序的挂钩,则实现该事件处理程序的对象将在该事件的对象的生命周期内一直留在内存中


托管的DirectX库有这样一个错误,它会导致大量内存泄漏。

特定于.NETCompactFramework:您必须显式地处理所有与图形相关的对象(图形、笔、SolidBrush、位图),否则它们将挂在内存中(在使用内存不足的设备时不是很好).

不完全是内存泄漏,但有一件事总是让我抓狂:


始终在使用SQL连接后关闭它们。

如果使用COM互操作,请在使用COM对象后使用Marshal.ReleaseComObject来释放运行时可调用包装器(RCW)

此外,如果您的COM对象具有返回另一个COM对象的属性或方法,请务必将其分配给变量,然后再释放它

即,这将泄漏GetFirstChild接收到的对象:

string name = myBigComObject.GetFirstChild().Name;
使用istead:

ChildComObject firstChild = myBigComObject.GetFirstChild()
string name = firstChild.Name;
Marshal.ReleaseComObject(firstChild);

仅当您希望事件发布者的持续时间比您长时,这才相关。在这些情况下,它确实可能是一个杀手,但我认为它的发生频率不足以保证“总是”——特别是因为这意味着使您的类成为可丢弃的,这会使其他地方的生活更加棘手。好吧,我们在谈论“观察列表”,而且我编辑了一点答案:)将变量设置为null很少有用,并且会使代码混乱。特别是,当局部变量不再在方法的其余部分中使用时,它将不会在发布模式中被视为根。通常,只要对象本身是根对象,实例变量就很有用。(续)静态变量往往与AppDomain的整个生命周期相关(例如缓存或工厂)。为了GC的缘故,我很少将变量设置为null。我同意我们不应该使代码杂乱无章,而且它并不是在所有情况下都能工作。但这是一个让我们震惊的地方,我想我会分享。乔恩-就像你在帖子中说的,最终取决于情况。这里发布的大多数答案(包括我的答案)可能都不相关,尤其是在GC越来越优化的情况下..我只是对不合格的建议持谨慎态度(即,没有说明它在哪里有用),通常弊大于利(即,没有帮助,但损害可读性)Jon,关于LINQ中数据的缓冲和流化,你在文章的后半部分有什么好的参考资料吗。听起来这本书应该是必读的,但到目前为止我还没有读到。@Eoin:我不想做太多广告,我相信我会在C#Depth的附录中为每个操作员列出这本书。也许我应该为这个主题添加一个社区维基问答……干杯,我已经将它添加到了办公室的“购买”图书列表中。哈哈——我不会仅仅凭自己的话就这么做。我有偏见:)而且见鬼,它甚至可能不会给出所有操作符的详细信息——我现在无法轻松检查。如果没有,请随时抱怨……我上周从当地图书馆拿了一本你的书。到目前为止读得不错。谢谢Ty关于“使用()”的回答涵盖了这一点。请删除。值得一提的是,请不要删除伊利亚关于“事件”的回复中包含的内容。请删除。两个答案都是在几秒钟内添加的。我的答案没有错,所以我不会删除它。