下面是关于C#中IDisposable接口的实现及为何这么实现的详解,包含两个示例说明。
什么是IDisposable接口
在C#中,当需要使用一些非托管资源时(例如文件、数据库连接、Socket等等),程序需要手动释放这些资源,否则会造成占用资源过多,程序出现异常或运行缓慢等问题。为了实现资源的自动释放,C#定义了IDisposable接口。
IDisposable接口有一个Dispose()方法,用于释放非托管资源。通过实现这个接口,可以使对象使用完后,能够自动释放所占用的非托管资源。
IDispose接口的实现方式
为了实现IDisposable接口,可以在类中加入以下代码:
public class MyClass : IDisposable
{
private bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this); //告知垃圾处理器,不必再调用此对象的Finalize方法。
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
//dispose managed resources
}
//dispose unmanaged resources
disposed = true;
}
~MyClass()
{
Dispose(false);
}
}
Dispose()方法是IDisposable接口中定义的唯一方法,意图提供对象的cleanup操作以便在释放对象时清理内存资源。无论对象是由关闭、清除、删除或释放非托管或其他类型的资源,都应实现Dispose()方法。
在Dispose()方法内部有一个Dispose(bool disposing)方法,其中disposing参数指示方法调用是由用户代码来释放对象还是由GC自动垃圾回收器来释放对象。最后,Dispose()方法会把对象从GC的Finalizer队列中移除。
此外,Dispose()方法的最后调用GC.SuppressFinalize(this)方法,告知垃圾处理器,不必再调用此对象的Finalize方法,在Dispose()方法已经清理干净所有的资源后,程序不需要等待GC再去调用Finalize()方法来执行相同的操作。
为何这么实现
在实现IDisposable接口时,为什么还要在析构函数中调用Dispose()方法并发送一个false参数呢?
这是为了避免调用被释放对象的可继承的Dispose()方法,因为在进行垃圾回收时,先执行对象的Finalize()方法,再销毁对象。如果不向Dispose()方法中传递disposing参数,当具有被释放对象的继承关系时,由于所有的析构函数调用了Dispose()方法,会产生一定的性能影响。
示例一:文件操作
以下代码演示了如何使用IDisposable接口来释放文件非托管资源:
public class FileUtil : IDisposable
{
private bool disposed = false;
private FileStream fileStream;
public FileUtil(string path)
{
if (!File.Exists(path))
File.Create(path);
this.fileStream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
fileStream.Close();
fileStream.Dispose();
}
disposed = true;
}
~FileUtil()
{
Dispose(false);
}
}
示例二:释放数据库连接
以下代码演示了如何使用IDisposable接口来释放数据库连接的非托管资源:
public class DBContext : IDisposable
{
private bool disposed = false;
private IDbConnection connection;
public DBContext(string connectionString)
{
connection = new SqlConnection(connectionString);
connection.Open();
}
public IDbCommand CreateCommand()
{
return connection.CreateCommand();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
if (connection.State != ConnectionState.Closed)
connection.Close();
connection.Dispose();
}
disposed = true;
}
~DBContext()
{
Dispose(false);
}
}
以上就是C#中IDisposable接口的实现及为何这么实现的详解,希望能对你有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#中IDispose接口的实现及为何这么实现详解 - Python技术站