我有以下代码:
MemoryStream foo(){ MemoryStream ms = new MemoryStream(); // write stuff to ms return ms; } void bar(){ MemoryStream ms2 = foo(); // do stuff with ms2 return; }
我分配的MemoryStream是否有可能以后不能被处理掉?
我有一个同行评审坚持我手动关闭它,我找不到信息来判断他是否有一个有效点.
你不会泄漏任何东西 - 至少在当前的实施中.
调用Dispose不会更快地清理MemoryStream使用的内存.它会被可行的通话,这可能会或可能不会对你有用后读/写调用停止您的流.
如果你完全确定你永远不想从MemoryStream转移到另一种流,那么不打算不调用Dispose会对你造成任何伤害.然而,这通常是一种很好的做法,部分原因是如果你做了改变以使用不同的Stream,你不希望被难以发现的bug所困扰,因为你很早就选择了简单的方法.(另一方面,有YAGNI的论点......)
无论如何,这样做的另一个原因是新实现可能会引入将在Dispose上释放的资源.
如果某些东西是Disposable,你应该总是处理它.您应该在bar()方法中使用using语句以确保ms2获得Disposed.
它最终会被垃圾收集器清理干净,但Dispose始终是一个好习惯.如果您在代码上运行FxCop,它会将其标记为警告.
是的,有泄漏,取决于你如何定义LEAK以及你的意思是多少......
如果通过泄漏你的意思是"内存仍然分配,无法使用,即使你已经完成使用它",后者你的意思是在调用dispose之后的任何时候,然后是的可能有泄漏,虽然它不是永久性的(即应用程序运行时的生命周期).
要释放MemoryStream使用的托管内存,您需要通过取消对它的引用来取消它,因此它立即有资格进行垃圾回收.如果你没有这样做,那么你从使用它之后就会创建一个临时的泄漏,直到你的引用超出范围,因为在此期间内存将无法分配.
using语句(简单地调用dispose)的好处是你可以在using语句中声明你的引用.当using语句结束时,不仅要调用dispose,而且你的引用超出了范围,有效地使引用无效并使你的对象立即有资格进行垃圾收集,而不需要你记得编写"reference = null"代码.
虽然没有立即引用某些东西不是经典的"永久性"内存泄漏,但它肯定具有相同的效果.例如,如果您保留对MemoryStream的引用(即使在调用dispose之后),并且在您的方法中稍稍向下,则尝试分配更多内存...仍由您引用的内存流使用的内存将不可用直到你使引用无效或它超出范围,即使你调用dispose并使用它完成.
这已经得到了解答,但我要补充一点,信息隐藏的老式原则意味着你可能在未来的某些时候想要重构:
MemoryStream foo() { MemoryStream ms = new MemoryStream(); // write stuff to ms return ms; }
至:
Stream foo() { ... }
这强调,主叫方不应该关心正在返回什么样的数据流,并有可能改变内部实现(如单元测试嘲笑时).
如果您未在条形实现中使用Dispose,则需要遇到麻烦:
void bar() { using (Stream s = foo()) { // do stuff with s return; } }
不需要调用.Dispose()
(或包装Using
).
您调用的原因.Dispose()
是尽快释放资源.
比如Stack Overflow服务器,我们有一组有限的内存和数千个请求.我们不想等待计划的垃圾收集,我们希望尽快释放该内存以便它可用对于新的传入请求.
所有流都实现IDisposable.在一个using语句中包装你的内存流,你会很好,花花公子.使用块将确保您的流无论如何都会关闭和处理.
无论你在哪里调用Foo,你都可以使用(MemoryStream ms = foo()),我认为你应该还可以.