我有这样的代码:
public class A: IDisposable
{
public CPlusCode cPlusCode{get;set;}
public void CallB()
{
using(bCode = new B(cPlusCode))
{
//do everything in B
}
}
public void Dispose()
{
cPlusCode.Dispose();
}
}
public class B: IDisposable
{
private CPlusCode cpp;
public B(CPlusCode cPlus)
{
cpp= cPlus;
}
public void Dispose()
{
cpp.Dispose();
//dispose everything
}
}
public static void Main()
{
for(int i=0; i<100000; i++)
{
var aObject = new A();
aObject .CallB();
}
}
问题在于,当我执行Main
时,B
占用了大量内存来实例化,从我的观察来看,程序吃掉的内存似乎没有被释放。 / p>
如果有其他对象指向它,可以释放内存吗?
答案 0 :(得分:6)
IDisposable
与回收托管内存无关。 IDisposable
允许类型释放未由垃圾收集处理的资源,例如句柄等。对于普通的.NET类型,垃圾收集器将在不再引用对象时处理回收内存。
答案 1 :(得分:2)
GC会在确定需要时运行,因此“及时”不相关。当它发生时它会发生;即它是非确定性的
答案 2 :(得分:2)
Dispose
只是一种方法。它根本不需要做任何事情。
在对象上调用Dispose
后,该对象仍然存在,但无法再安全使用。但是,运行时无助于强制执行此操作。 Dispose
的一个“可靠”实现(一个旨在帮助捕获错误的实现)会在对象内部将_disposed
标志设置为true,如果对象上的每个其他方法都将抛出ObjectDisposedException
该标志为true(Dispose
方法本身应该静默忽略进一步的调用)。但这完全取决于实施者在实施这种模式方面的进展程度。
一个例子是FileStream
。当它有一个打开的文件时,进程的句柄计数将增加1.当你在其上调用Dispose
时,句柄计数将减少。但这只是因为FileStream
的作者编写了他们的Dispose
方法来实现这一目标。
这会导致下一个问题 - 您可以在任务管理器中看到进程的句柄计数,这是一个非常简单的计数器,但您如何测量内存使用情况?请注意,任务管理器中显示的数字远非简单的措施。
答案 3 :(得分:0)
从我的观察看起来似乎是 程序吃掉的记忆不是 释放了。
这是完全正常的。该程序将挂起一定数量的未使用的内存,如果系统确实需要,它将被释放。
有人可能会认为性能最好的方法是尽可能减少内存使用量,但实际上却是另一种方式。由于拥有大量未使用的内存,计算机根本没有任何好处,因此为了获得最佳性能,应用程序不应该做额外的工作来最小化内存使用量,直到真正需要它为止。
如果,Dispose可以释放内存 还有其他指向的对象 它?
是,不......
调用对象上的Dispose不会释放对象本身,但是如果对象包含其他对象,则可以通过Dispose方法释放这些对象。这本身不会释放任何内存,但它会让垃圾收集器在下次运行时执行它。
答案 4 :(得分:0)
如果您已正确实现它,并且您正在释放Dispose()
内的所有非托管资源,那么在您释放对该对象的所有引用后,应该收集该对象(或者更好,有资格进行收集)。 / p>
但请注意,您未在示例中处置对象A
,该对象也是IDisposable
。如果A
包含对B
的引用,并且您没有处置A
,那么这可能会延迟B
的收集(如果A
有一些非托管的东西,可能会创建对A
)的引用。
由于示例中A
似乎引用了非托管代码,A
应该负责处理它。