当我将它传递给 IDisposable class 时,我需要 Dispose Stream 吗?
Do i need to Dispose Stream when i Pass it to IDisposable class?
我写了一段代码。我想确保以正确的方式处理对象。
我有这样的一次性 Class
用于从非托管资源中读取一些数据。
class MyFileReader : IDisposable
{
private readonly FileStream _stream;
public MyFileReader(FileStream stream)
{
_stream = stream;
}
public void Dispose()
{
_stream.Dispose();
}
}
目前在我的程序中我是这样处理对象的。
using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (MyFileReader reader = new MyFileReader(stream))
{
//...
}
}
这对我来说似乎没问题。后来我注意到 Classes 是通过引用传递的,所以如果我处理其中一个,就不需要处理另一个。
我的问题是我可以做这样的事情吗?
using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
MyFileReader reader = new MyFileReader(stream);
// Remove IDisposable from MyFileReader and stream will close after using.
}
还是这个?
FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
// stream will close after using.
using (MyFileReader reader = new MyFileReader(stream))
{
//...
}
如果 MyFileReader 正在访问一些非托管资源并且您需要在此代码块之后显式调用 Disponse 方法,那么您必须坚持当前的实现。
在第二种实现中,不会为MyFileReader 对象调用Dispose 方法。 (直到你可能在你不知道什么时候调用的析构函数中调用它)
如果您不喜欢嵌套使用,那么您可以选择第二种方法,并在 MyFileReader class 的 Dispose() 方法实现中显式处理 Stream。如果此流仅由 MyFileReader 使用,那么让 MyFileReader 管理其生命周期并处理它是一个很好的做法。
是的,你可以编写那样的代码。
但是,不,你不应该那样做。
您的 class 看起来像 XxxxReader classes 的一个,按照惯例拥有他们从中读取的流。因此,您的 MyFileReader
class 预期 处理内部流。当您知道每个对象的生命周期结束时,您通常还希望处理每个一次性对象。
请注意,有时它会导致对某些对象进行多次 Dispose
调用(这应该是 IDisposable
的实现所期望的)。虽然它有时可能会导致代码分析警告,但如果一个人经常尝试通过跳过一些 "optimize" 次对 Dispose
的调用,那么它总比错过 Dispose 调用要好。
另一种方法是公开读取内容的方法,按照惯例不应获得 stream/reader 的所有权,例如:
using(stream....)
{
var result = MyFileReader.ReadFrom(stream);
}
许多框架流包装 类 具有控制流处理行为的 leaveOpen
参数的构造函数重载。
示例包括 StreamReader
、BinaryReader
、GZipStream
。
还有属性方法,SharpZipLib例子:
using (var zip = new ZipInputStream(stream) { IsStreamOwner = false }) { ... }
我写了一段代码。我想确保以正确的方式处理对象。
我有这样的一次性 Class 用于从非托管资源中读取一些数据。
class MyFileReader : IDisposable
{
private readonly FileStream _stream;
public MyFileReader(FileStream stream)
{
_stream = stream;
}
public void Dispose()
{
_stream.Dispose();
}
}
目前在我的程序中我是这样处理对象的。
using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (MyFileReader reader = new MyFileReader(stream))
{
//...
}
}
这对我来说似乎没问题。后来我注意到 Classes 是通过引用传递的,所以如果我处理其中一个,就不需要处理另一个。
我的问题是我可以做这样的事情吗?
using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
MyFileReader reader = new MyFileReader(stream);
// Remove IDisposable from MyFileReader and stream will close after using.
}
还是这个?
FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
// stream will close after using.
using (MyFileReader reader = new MyFileReader(stream))
{
//...
}
如果 MyFileReader 正在访问一些非托管资源并且您需要在此代码块之后显式调用 Disponse 方法,那么您必须坚持当前的实现。
在第二种实现中,不会为MyFileReader 对象调用Dispose 方法。 (直到你可能在你不知道什么时候调用的析构函数中调用它)
如果您不喜欢嵌套使用,那么您可以选择第二种方法,并在 MyFileReader class 的 Dispose() 方法实现中显式处理 Stream。如果此流仅由 MyFileReader 使用,那么让 MyFileReader 管理其生命周期并处理它是一个很好的做法。
是的,你可以编写那样的代码。
但是,不,你不应该那样做。
您的 class 看起来像 XxxxReader classes 的一个,按照惯例拥有他们从中读取的流。因此,您的 MyFileReader
class 预期 处理内部流。当您知道每个对象的生命周期结束时,您通常还希望处理每个一次性对象。
请注意,有时它会导致对某些对象进行多次 Dispose
调用(这应该是 IDisposable
的实现所期望的)。虽然它有时可能会导致代码分析警告,但如果一个人经常尝试通过跳过一些 "optimize" 次对 Dispose
的调用,那么它总比错过 Dispose 调用要好。
另一种方法是公开读取内容的方法,按照惯例不应获得 stream/reader 的所有权,例如:
using(stream....)
{
var result = MyFileReader.ReadFrom(stream);
}
许多框架流包装 类 具有控制流处理行为的 leaveOpen
参数的构造函数重载。
示例包括 StreamReader
、BinaryReader
、GZipStream
。
还有属性方法,SharpZipLib例子:
using (var zip = new ZipInputStream(stream) { IsStreamOwner = false }) { ... }