Menu
CoddyTech

IDisposable 和 using 语句

本课属于 Coddy C# 学习旅程的“面向对象编程”单元。第 45 课,共 70 课。

有些对象会持有垃圾回收器无法自动清理的资源,例如文件句柄、数据库连接和网络套接字。IDisposable 接口提供了一种标准方式,让你在用完这些资源后释放它们。

类通过提供 IDisposable 接口的 Dispose() 方法来实现它:

public class FileHandler : IDisposable
{
    private bool disposed = false;
    
    public void Dispose()
    {
        if (!disposed)
        {
            Console.WriteLine("Releasing resources...");
            disposed = true;
        }
    }
}

你可以手动调用 Dispose(),但如果在执行到那一行之前发生异常,该怎么办?using 语句可以确保完成清理,即使出现问题也是如此:

using (FileHandler handler = new FileHandler())
{
    // 使用 handler 进行操作
}  // 这里会自动调用 Dispose()

现代 C# 提供了更简洁的语法,即 using 声明。当对象超出作用域时,它会释放该对象:

void ProcessFile()
{
    using FileHandler handler = new FileHandler();
    // 使用 handler
}  // 方法结束时会调用 Dispose()

using 语句适用于任何实现了 IDisposable 的类型。StreamReader、SqlConnection 和 HttpClient 等内置类都实现了这个接口,因此资源管理变得简单可靠。

challenge icon

挑战

简单

我们来构建一个数据库连接模拟器,使用 IDisposable 接口和 using 语句演示正确的资源管理。你将创建一个类,用来跟踪连接的打开和关闭,确保资源始终得到正确释放。

你需要将代码分布在两个文件中:

  • DatabaseConnection.cs:在 DataAccess 命名空间中创建一个实现 IDisposable 的 DatabaseConnection 类。你的连接应该:
    • 包含一个通过构造函数设置的 ConnectionName 属性(字符串,只读)
    • 使用私有布尔字段跟踪连接是否已释放
    • 在对象创建时(构造函数中)打印 Connection opened: {ConnectionName}
    • 实现 Dispose() 方法,打印 Connection closed: {ConnectionName},但仅在对象尚未释放时打印(防止重复释放)
    • 包含一个 Query(string sql) 方法,返回 Executing on {ConnectionName}: {sql}
  • Program.cs:在主文件中,使用 using 语句管理数据库连接,以展示正确的资源管理。创建一个连接,执行查询,并让 using 代码块自动完成清理。

你会收到两个输入:

  • 连接名称(例如,MainDB)
  • 要执行的 SQL 查询(例如,SELECT * FROM Users)

使用 using 语句创建连接。在代码块中,调用 Query 方法并打印其结果。using 代码块结束时,会自动调用 Dispose()。

例如,如果输入是 MainDB 和 SELECT * FROM Users,输出应为:

Connection opened: MainDB
Executing on MainDB: SELECT * FROM Users
Connection closed: MainDB

注意,using 代码块结束时,连接会自动关闭。你不必记得手动调用 Dispose()。这种模式可以确保资源始终得到清理,即使代码块中发生异常也不例外!

亲手试试

using System;
using DataAccess;

class Program
{
    public static void Main(string[] args)
    {
        string connectionName = Console.ReadLine();
        string sqlQuery = Console.ReadLine();
        
        // TODO:使用 'using' 语句创建 DatabaseConnection
        // 在 using 代码块中:
        // 1. 使用 sqlQuery 调用 Query 方法
        // 2. 打印 Query 方法的结果
        // using 代码块结束时会自动调用 Dispose 方法
        
    }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C# 在线编译器