代表可以导致内存泄漏吗? GC.TotalMemory(true)似乎表明了这一点

using System; internal static class Test { private static void Main() { try { Console.WriteLine("{0,10}: Start point", GC.GetTotalMemory(true)); Action simpleDelegate = SimpleDelegate; Console.WriteLine("{0,10}: Simple delegate created", GC.GetTotalMemory(true)); Action simpleCombinedDelegate = simpleDelegate + simpleDelegate + simpleDelegate; Console.WriteLine("{0,10}: Simple combined delegate created", GC.GetTotalMemory(true)); byte[] bigManagedResource = new byte[100000000]; Console.WriteLine("{0,10}: Big managed resource created", GC.GetTotalMemory(true)); Action bigManagedResourceDelegate = bigManagedResource.BigManagedResourceDelegate; Console.WriteLine("{0,10}: Big managed resource delegate created", GC.GetTotalMemory(true)); Action bigCombinedDelegate = simpleCombinedDelegate + bigManagedResourceDelegate; Console.WriteLine("{0,10}: Big combined delegate created", GC.GetTotalMemory(true)); GC.KeepAlive(bigManagedResource); bigManagedResource = null; GC.KeepAlive(bigManagedResourceDelegate); bigManagedResourceDelegate = null; GC.KeepAlive(bigCombinedDelegate); bigCombinedDelegate = null; Console.WriteLine("{0,10}: Big managed resource, big managed resource delegate and big combined delegate removed, but memory not freed", GC.GetTotalMemory(true)); GC.KeepAlive(simpleCombinedDelegate); simpleCombinedDelegate = null; Console.WriteLine("{0,10}: Simple combined delegate removed, memory freed, at last", GC.GetTotalMemory(true)); GC.KeepAlive(simpleDelegate); simpleDelegate = null; Console.WriteLine("{0,10}: Simple delegate removed", GC.GetTotalMemory(true)); } catch (Exception e) { Console.WriteLine(e); } Console.ReadKey(true); } private static void SimpleDelegate() { } private static void BigManagedResourceDelegate(this byte[] array) { } } 

产量

 GC.TotalMemory(true) 105776: Start point 191264: Simple delegate created 191328: Simple combined delegate created 100191344: Big managed resource created 100191780: Big managed resource delegate created 100191812: Big combined delegate created 100191780: Big managed resource, big managed resource delegate and big combined delegate removed, but memory not freed 191668: Simple combined delegate removed, memory freed, at last 191636: Simple delegate removed 

有趣的案例。 这是解决方案:

在此处输入图像描述

组合代表是观察纯粹的 :看起来代表是不可变的外部。 但在内部,现有的代表正在被修改 。 出于性能原因,它们在某些条件下共享相同的_invocationList (针对少数代表连接到同一事件的场景进行优化)。 不幸的是, simpleCombinedDelegatebigMgdResDelegate引用了bigMgdResDelegate ,这会导致内存保持活动状态。

我可能在这里忽略了这一点,但垃圾收集在设计上是非确定性的。 因此,由.NET框架决定何时回收内存。

您可以在一个简单的循环中运行GC.GetTotalMemory并获得不同的数字。 也许并不奇怪,因为文档指定返回的数字是近似值。