我最近在Jeffery Richter的“CLR via C#”中读过这篇文章;
重要如果某个类定义了字段类型的字段 实现dispose模式,类本身也应该实现 处置模式。 Dispose方法应该处理该对象 该领域提到的。这允许使用该类的人来打电话 处理它,然后释放对象使用的资源 本身。
在以下示例中是否会这样?
public class SomeClass
{
private readonly StreamReader _reader; //a disposable class
public SomeClass(StreamReader reader)
{
_reader = reader;
}
}
虽然StreamReader是一个一次性类,它的intance已经通过构造函数传递,因此它可能会被引用到其他地方,因此在SomeClass上实现IDisposable以便_reader可以被处理似乎是一个坏主意。 Jeffery Richter试图使其仅适用于在该类中实例化一次性类的实例的类吗?
答案 0 :(得分:2)
虽然StreamReader是一个一次性类,但它的实例却是 通过构造函数传入,因此它可能会 在其他地方引用,因此在SomeClass上实现IDisposable
这真的取决于。通常,当您持有一次性资源时,实施IDisposable
是一个很好的经验法则。但是,如果您知道其他人要持有对所述资源的引用这一事实,您可以在类构造函数中创建一个重载,如果他想要您处置,则显式询问调用者:
public class SomeClass : IDisposable
{
private readonly StreamReader _reader; //a disposable class
private bool shouldDispose;
public SomeClass(StreamReader reader) : this(reader, true)
{
}
public SomeClass(StreamReader reader, bool shouldDispose)
{
_reader = reader;
this.shouldDispose = shouldDispose;
}
public void Dispose()
{
if (shouldDispose)
{
Dispose(true);
}
}
protected void Dispose(bool isDisposing)
{
if (isDisposing)
{
_reader.Dispose();
}
}
}
答案 1 :(得分:1)
几乎从来没有一个场景总是"总是"是合适的。在很多场景中,这既可以是真实的,也可以是不正确的。这是以下示例
public class DbSomething : IDisposable
{
private SqlConnection _connection;
public DbSomething (SqlConnection connection){
_connection = connection;
}
~DbSomething() {
Dispose(true);
}
bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
_connection.Dispose();
}
disposed = true;
}
}
现在,如果此类实现了IDisposable并处理了连接,那么如果要在其他地方使用此连接会发生什么?此类正在修改不属于它的对象的状态。
因此,
public class DbSomething : IDisposable
{
private SqlConnection _connection;
public DbSomething (){
_connection = new SqlConnection();
}
//same dispose
}
此类可以控制SqlConnection对象。它创造了它,它应该处理它。那么,如果您将SqlConnection公开以供其他内容使用,会发生什么?
public class DbSomething
{
public SqlConnection Connection;
public DbSomething (){
Connection = new SqlConnection();
}
//same dispose
}
现在我仍然默认,该对象创建它,该对象应该摆脱它,但根据代码,这可能是不可能的。它可能只是一个工厂来创建一个最终需要处理的长寿命对象,之后不再需要创建对象。在这种情况下,创建对象处理它的情况成为一个问题,所以即使前两个场景看起来像是好主意,偏离它们也是合适的选择。
该方法也可能是这样的,它甚至不会将一个实例保存到要处置的对象:
public class DbSomething
{
public SqlConnection CreateSqlConnection () => return new SqlConnection();
}