我有以下类在内部使用BinaryReader并实现IDisposable。
class DisposableClass : IDisposable { private BinaryReader reader; public DisposableClass(Stream stream) { reader = new BinaryReader(stream); } protected virtual void Dispose(bool disposing) { if (disposing) { ((IDisposable)reader).Dispose(); // reader.Dispose();// this won't compile } } public void Dispose() { this.Dispose(true); } }
我已经发现我需要将BinaryReader转换为IDisposable以便能够在其上调用Dispose,但我不明白为什么我不能直接调用Dispose()方法而不转换为IDisposable?< / p>
答案 0 :(得分:7)
它无效,因为Dispose
上的BinaryReader
方法已明确实施。
而不是隐式实现,如:
public void Dispose()
{
}
......已明确实施,如:
void IDisposable.Dispose()
{
}
...这意味着它只能通过IDisposable
界面访问。因此,您必须先将实例强制转换为IDisposable
。
答案 1 :(得分:3)
扩展我的评论here,BinaryReader
类未正确实现Dispose模式。
在Reflector中查看此类,它看起来像这样(对于.NET 3.5):
public class BinaryReader : IDisposable
{
public virtual void Close()
{
this.Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
Stream stream = this.m_stream;
this.m_stream = null;
if (stream != null)
{
stream.Close();
}
}
this.m_stream = null;
this.m_buffer = null;
this.m_decoder = null;
this.m_charBytes = null;
this.m_singleChar = null;
this.m_charBuffer = null;
}
void IDisposable.Dispose()
{
this.Dispose(true);
}
}
这里的问题是,通过使IDisposable.Dispose()
显式接口实现,它会迫使开发人员调用Close()
而不是Dispose()
。
在这种情况下,我们有一个不平衡语义的例子。从来没有打电话给读者“打开”,所以“关闭”读者并不直观。
更进一步,为了调用Dispose(),你必须明确地转换为IDisposable
,这不是你通常需要做的事情。您可以选择直接调用Dispose(bool)
,但是您如何知道布尔参数应该是什么?
要正确遵循该模式,它应该被表示为:
public class BinaryReader : IDisposable
{
public virtual void Close()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
Stream stream = this.m_stream;
this.m_stream = null;
if (stream != null)
{
stream.Close();
}
}
this.m_stream = null;
this.m_buffer = null;
this.m_decoder = null;
this.m_charBytes = null;
this.m_singleChar = null;
this.m_charBuffer = null;
}
public void Dispose()
{
this.Close();
}
}
这样您就可以拨打Close()
或Dispose()
,在这种情况下,任一呼叫都会继续调用Dispose(true)
。 (这与实际实现的流程相同,只需调用Close()
或((IDisposable)reader).Dispose()
)。
幸运的是(或者不幸的是,取决于您选择查看它的方式),因为BinaryReader
确实实现了IDisposable
接口,因此在using语句中允许使用它:
using (BinaryReader reader = new BinaryReader(...))
{
}
答案 2 :(得分:1)
实际上他们选择使用Close()而不是Dispose() Dispose已经明确实现。这就是为什么你看不到它。
然而,Close与dispose的作用相同,这是他们希望您使用的方法。 Reflector为Close方法
提供以下反汇编public virtual void Close()
{
this.Dispose(true);
}
使用Close()是因为它是二进制阅读器上下文中更好的单词选择。