在下面的Dispose函数中,如果从终结器调用我们,则不会处理我们的流实例。 (是的,我知道这是一个有点复杂的Dispose版本,它应该是虚拟的保护,但这是它在我引用的源代码中编写的方式,请参阅下面的Essential C#5.0链接)
class Foo
{
FileInfo File;
Stream Stream;
// yada yada yada more code goes here...
public void Dispose(bool disposing)
{
if (disposing)
{
if (Stream != null)
{
Stream.Dispose();
}
}
if (File != null)
{
File.Delete();
}
}
}
据我了解,这是由于GC释放对象(包括实例成员)的顺序不可预测。
但是,如果符合以下条件,上面的代码肯定会引发异常(我测试过它)。
因此File.Delete()将失败并抛出System.IO.IOException异常。
所以我的问题是, 确保流关闭和文件被删除的正确方法是什么? (即使开发人员忘记手动处理对象) 显然访问Stream成员(在处理== false时)是不安全的,所以必须有办法。
请注意 FileOptions.DeleteOnClose不是选项。这就是动机:我有一个类似Open的和Close的文件类,并且在方法边界使用文件(即读取数据),我不希望在实际使用结束之前删除文件。
谢谢, 奥菲尔
答案 0 :(得分:0)
为什么不实施推荐(由Microsoft)模式?
// When implementing Dispose, mark it my implementing
// IDisposable interface. It make you code more readable,
// allow to put using(...) {...} etc.
class Foo: IDisposable {
FileInfo File; // <- class, not struct
Stream Stream; // <- class, not struct
...
// Just useful thing, esp. while debugging
public Boolean IsDisposed {
get;
private set;
}
// Since Foo is not a sealed class be ready that
// it could be inherited: "protected virtual"
protected virtual void Dispose(bool disposing) {
// .Net often let you call Dispose many time, inc. on disposed instances;
// The same should do we
if (IsDisposed)
return;
// You can access classes (not structs) in "if (disposing) {...}" only
if (disposing) {
if (!Object.ReferenceEquals(null, Stream))
Stream.Dispose();
if (!Object.ReferenceEquals(null, File))
File.Delete();
}
IsDisposed = true;
}
// MS recommendation
public void Dispose() {
Dispose(false);
GC.SuppressFinalize(this);
}
// No finalizer here: finalizer just make you potential error
// (resourse leak or Access Violation) unstable and so harder
// to detect and correct.
}
每当开发人员想要使用该类时,他/她就会简单地使用
using (var foo = new Foo(...)) {
...
}