Stream.Dispose是否总是调用Stream.Close(和Stream.Flush)
如果我有以下情况:
StreamWriter MySW = null; try { Stream MyStream = new FileStream("asdf.txt"); MySW = new StreamWriter(MyStream); MySW.Write("blah"); } finally { if (MySW != null) { MySW.Flush(); MySW.Close(); MySW.Dispose(); } }
我可以只是调用MySW.Dispose()
并跳过closures即使它提供? 有什么Stream implimentations不能按预期工作(像CryptoStream)?
如果不是,那么下面就是不好的代码:
using (StreamWriter MySW = new StreamWriter(MyStream)) { MySW.Write("Blah"); }
我可以只是调用MySW.Dispose()并跳过closures即使它提供?
是的,就是这样。
是否有任何Stream实现不能按预期工作(如CryptoStream)?
假设一个对象实现了IDisposable
,它可以很好地处理它自己。
如果没有,那么这将是一个错误。
如果不是,那么下面就是不好的代码:
不,该代码是处理实现IDisposable
对象的推荐方式。
在接受和处置的接受答案中有更多优秀的信息- 要调用哪一个?
我使用reflection器,发现System.IO.Stream.Dispose
看起来像这样:
public void Dispose() { this.Close(); }
正如丹尼尔·布鲁克纳(Daniel Bruckner)提到的,处置和closures实际上是一回事。
但是Stream在处理/closures时不调用Flush()。 FileStream(和我认为任何其他与caching机制的stream)不处理时调用Flush()。
如果您正在扩展Stream或MemoryStream等,则在需要处理/closures时,需要实现对Flush()的调用。
StreamWriter.Dispose()和Stream.Dispose()都释放对象所拥有的所有资源。 他们都closures了基础stream。
Stream.Dispose()的源代码(请注意,这是实现细节,所以不要依赖它):
public void Dispose() { this.Close(); }
StreamWriter.Dispose()(与Stream.Dispose()相同):
protected override void Dispose(bool disposing) { try { // Not relevant things } finally { if (this.Closable && (this.stream != null)) { try { if (disposing) { this.stream.Close(); } } finally { // Not relevant things } } } }
不过,我通常在处理它们之前暗中closuresstream/ streamwriters – 我认为它看起来更干净。
所有标准stream(FileStream,CryptoStream)将在closures/处理时尝试刷新。 我想你可以依靠任何Microsoftstream实现这个。
因此,如果刷新失败,Close / Dispose可能会抛出exception。
实际上,IIRC在FileStream的.NET 1.0实现中存在一个错误,那就是如果flush引发exception,将无法释放文件句柄。 这是通过添加一个try / finally块到Dispose(boolean)方法在.NET 1.1中修复的。
对于需要手动closures的对象,应尽一切努力在使用块中创build对象。
//Cannot access 'stream' using (FileStream stream = File.Open ("c:\\test.bin")) { //Do work on 'stream' } // 'stream' is closed and disposed of even if there is an exception escaping this block // Cannot access 'stream'
通过这种方式,永远不会在using子句的上下文中错误地访问'stream',并且文件总是被closures。
我查看了Stream类的.net源文件,它具有以下内容,表明可以。
// Stream used to require that all cleanup logic went into Close(), // which was thought up before we invented IDisposable. However, we // need to follow the IDisposable pattern so that users can write // sensible subclasses without needing to inspect all their base // classes, and without worrying about version brittleness, from a // base class switching to the Dispose pattern. We're moving // Stream to the Dispose(bool) pattern - that's where all subclasses // should put their cleanup starting in V2. public virtual void Close() { Dispose(true); GC.SuppressFinalize(this); } public void Dispose() { Close(); }
Stream.Close
是通过调用Stream.Close
来实现的,反之亦然 – 所以这些方法是等价的。 Stream.Close
只是因为closuresstream听起来比Stream.Close
stream更自然。
此外,您应该尽量避免显式调用此方法,而是使用using
语句来获得正确的免费exception处理。