MemoryStream.Close()或MemoryStream.Dispose()


Answers:


130

Close()Dispose(),当在上被调用时MemoryStream,只能起到两件事的作用:

  • 将对象标记为已处置,以便将来意外使用该对象将引发异常。
  • 可能有1个版本发布了对托管对象的引用,根据GC的实现,这可以使GC的工作稍微容易一些。(对于当今的GC算法而言,它并没有真正的区别,因此这是学术讨论的重点,对现实世界没有重大影响。)

MemoryStream没有任何非托管资源可处置,因此从技术上讲您不必处置它。不丢弃a的效果MemoryStream与删除对a的引用大致相同byte[]-GC将以相同的方式清理这两个引用。

我该叫哪一个?有必要同时调用两者吗?

Dispose()流的方法,直接委托给Close()方法2,这样既做同样的事情。

如果我已经呼叫其中一个,另一个会抛出异常吗?

具体的文档IDisposable.Dispose()指出,可以安全地Dispose()在任何对象3上多次调用。(如果对于特定的类不是这样,则该类IDisposable将以违反其合同的方式实现接口,这将是一个错误。)

这么说:不管您是否处置,这并没有太大的区别MemoryStream。它拥有Close/Dispose方法的唯一真正原因是因为它继承自Stream,这要求这些方法作为其合同的一部分,以支持确实具有非托管资源(例如文件或套接字描述符)的流。


1 Mono的实现不会释放该byte[]参考。我不知道Microsoft实现是否可以。

2 “此方法调用Close,然后调用Stream.Dispose(Boolean)。”

3 “如果多次调用对象的Dispose方法,则该对象必须忽略在第一个调用之后的所有调用。”


请注意,MemoryStream仅当出于某种原因持有对已处置流对象的引用时,有关处置使GC的工作更容易的部分才适用。
爱德华·布雷

@EdwardBrey是的。这取决于GC的实现。当今所有流行的CLR实现都使用标记-扫描GC的某些变体,因此,这实际上是一个学术讨论-今天的GC不会显示任何区别。
cdhowie

3
关于您的脚注1,根据.NET参考源 .Dispose()也不发布内部版本byte[]。它集的唯一资源null_lastReadTask其只在该方法中使用Task<int> ReadAsync(byte[], int, int, CancellationToken)。除了设置一个变量空它是所有设置_isOpen_writable以及_expandablefalse
Scott Chamberlain 2014年

10

以上都不是。您无需致电CloseDispose

MemoryStream不包含任何非托管资源,因此唯一需要回收的资源是内存。MemoryStream当您的代码不再引用时,垃圾回收期间将与对象的其余部分一起回收内存MemoryStream

如果您有对的长期引用,则MemoryStream可以将该引用设置为null以允许MemoryStream对进行垃圾回收。CloseDispose释放蒸汽缓冲器和MemoryStream适当的物体。

由于既Stream没有MemoryStream终结器也没有终结器,因此无需调用CloseDispose导致GC.SuppressFinalize调用它来优化垃圾回收。没有终结器可以抑制。

MemoryStream的文档是这样写的:

此类型实现IDisposable接口,但实际上没有任何资源可配置。这意味着不需要直接调用Dispose()或使用诸如using(在C#中)或Using(在Visual Basic中)之类的语言构造来处置它。


8

您可以using为此使用块。Dispose超出范围时,它将自动调用。

例:

using (MemoryStream ms = new MemoryStream())
{
    // Do something with ms..
}
// ms is disposed here

希望这会有所帮助。



5

我该叫哪一个?

任何一位。

有必要同时调用两者吗?

不,任何一个都足够。

如果我已经呼叫其中一个,另一个会抛出异常吗?

不,一次性模式声明后续对Dispose的调用不会造成负面影响。


刚刚在一个实时应用程序中经历了这一过程。Close和Dispose在CLR 4.5中的行为不同。处置应该足够,但是如果需要,可以先致电关闭然后处置。
rkralston

4

下面的代码是Stream.Dispose从反射器,您可以看到,如果您进行处理,则不需要关闭(使用using时是隐式的)

public void Dispose()
{
    this.Close();
}

3

调用Close()将在内部调用Dispose()释放资源。

有关更多信息,请参见此链接: msdn



1

在.NET 3.5(尚未检查其他版本)中,在处理MemoryStream时按以下顺序调用方法:

  1. Stream.Dispose()
    • 只需调用关闭
  2. Stream.Close()
    • 调用Dispose(true),然后调用GC.SuppressFinalize(this)
  3. MemoryStream.Dispose(true)
    • 将_isOpen,_writable和_expandable标志设置为false
  4. Stream.Dispose(true)
    • 如果激活则关闭异步事件

0

作为第一个解决方案,建议尽可能使用using语句。这是在这里描述:http : //msdn.microsoft.com/en-us/library/yh598w02.aspx

当IDisposable对象的生存期仅限于一个方法时,应在using语句中声明并实例化它。using语句以正确的方式调用对象上的Dispose方法,并且(当您使用前面显示的方法时)它还会导致对象本身在调用Dispose时就超出范围。在using块中,该对象是只读的,无法修改或重新分配。

正如大多数.NET框架类中的其他人所建议的那样,现在来提一个问题,Close()和Dispose()之间没有区别,并且调用这两种方法中的哪一个都不重要。您应该打一个电话,但不能两个都打。但是,也有例外

有例外;例如,System.Windows.Forms.Form和System.Data.SqlClient.SqlConnection对于Close()和Dispose()具有不同的行为。

有关完整的详细信息,您可以在此处检查:https : //blogs.msdn.microsoft.com/kimhamil/2008/03/15/the-often-non-difference-between-close-and-dispose/

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.