C#的IDisposable接口是什么?如何正确实现Dispose模式?

来源:这里教程网 时间:2026-02-21 17:30:22 作者:

IDisposable 接口是 C# 中用于释放非托管资源(如文件句柄、数据库连接、网络套接字等)的标准机制。它只包含一个方法:

Dispose()
,通过手动调用或使用
using
语句来确保资源被及时清理。

如果类持有非托管资源或实现了 IDisposable 的对象,就应实现 IDisposable 接口,避免资源泄漏。

基本用法:IDisposable 接口

定义:

IDisposable 只有一个方法:

void Dispose();

常见用法是在

using
块中使用:

using (var file = File.Open("data.txt", FileMode.Open))
{
    // 使用文件流
} // 自动调用 Dispose()

正确实现 Dispose 模式

当类直接管理非托管资源时,需要完整实现 Dispose 模式,包括析构函数和资源释放逻辑。

关键点:

实现
IDisposable
接口
提供受保护的虚方法
Dispose(bool)
避免重复释放 必要时添加析构函数(仅非托管资源)

标准实现模板:

public class MyClass : IDisposable
{
    private IntPtr _handle; // 非托管资源示例
    private FileStream _fileStream; // 托管资源
    private bool _disposed = false;
<pre class="brush:php;toolbar:false;">public MyClass()
{
    _handle = AllocateSomeNativeResource();
    _fileStream = File.Open("log.txt", FileMode.Create);
}
protected virtual void Dispose(bool disposing)
{
    if (_disposed) return;
    if (disposing)
    {
        // 释放托管资源
        _fileStream?.Dispose();
    }
    // 释放非托管资源
    ReleaseNativeResource(_handle);
    _handle = IntPtr.Zero;
    _disposed = true;
}
public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this); // 避免析构函数再次释放
}
~MyClass()
{
    Dispose(false); // 不释放托管资源,仅清理非托管部分
}

}

何时需要析构函数?

只有在直接持有非托管资源(如指针、句柄)时才需要析构函数。它作为“安全网”,防止用户忘记调用 Dispose。

注意: 析构函数运行时机不确定,不应依赖它及时释放资源 一旦调用了
Dispose()
,应调用
GC.SuppressFinalize(this)
避免重复处理

继承场景下的处理

若类可能被继承,

Dispose(bool)
应声明为
protected virtual
,子类可重写以添加自己的清理逻辑。

protected override void Dispose(bool disposing)
{
    if (!_disposed)
    {
        if (disposing)
        {
            // 清理子类的托管资源
        }
<pre class="brush:php;toolbar:false;">    // 清理子类的非托管资源
    base.Dispose(disposing);
}

}

基本上就这些。核心是区分托管与非托管资源,合理组织释放逻辑,利用 using 确保调用,避免资源泄漏。

相关推荐