"Dispose"是否释放设置为同一对象的类的每个实例?



由于SqlConnectionSqlCommand实现了IDisposable,我将它们包装在using语句中。

但是,我在方法中创建它们,然后将它们传递给 using 语句,因此想知道using的右大括号是否会处理该方法创建的SqlCommand

所以我试了这个:

private void button1_Click(object sender, EventArgs e)
{
    SqlCommand command = new SqlCommand();
    command.CommandTimeout = 10;
    command.Disposed += s_Disposed;    
    using (SqlCommand tempCommand = command) { }//This is where even "command" is supposed to get disposed.
    Text = command.CommandTimeout.ToString();
}
void s_Disposed(object sender, EventArgs e)
{
    MessageBox.Show("Disposed");
}

并且惊讶地看到MessageBox确实显示暗示它已被处理,但文本是"10"。

为什么?

一般来说,实现IDisposable的对象(例如SqlConnection)之所以这样做,是因为宇宙中某个地方的某些东西(如SQL服务器)被要求代表它们做某事(例如打开并保持连接),并且会一直这样做,直到另有指示。 通常,如果IDisposable对象要遵循它期望接收的请求(例如执行 SQL 操作),则需要让这些外部事物代表它执行操作。 Dispose的目的不是实际销毁调用它的对象,而是让对象知道,由于没有其他人需要它,它应该反过来让任何代表它做任何事情的外部实体知道他们不再需要这样做(例如,因为没有人会要求SqlConnection执行更多的请求, 它不再需要让服务器为其保持连接打开)。

如果在对一个对象调用Dispose之后,要求它做一些需要外部实体帮助的事情,而外部实体不再可用,那么对象最好自己扔ObjectDisposedException而不是让动作以其他方式失败。 另一方面,如果要求一个对象做一些可以在不使用外部实体的情况下完美完成的事情,那么它这样做通常是合适的。 使用 IDisposable 对象的代码通常应避免在未明确记录为仍然可用的Dispose之后使用任何成员,并且应避免假设在类的一个版本上Dispose后仍然有用的成员将始终这样做。 尽管如此,在许多情况下,类指定特定成员可以在Dispose之后使用比努力确保它们不能使用更好。

它确实正确释放了SqlCommand实例,并且对它有多少引用并不重要。无论如何,它们都指向同一个实例。

但是,即使在已释放的对象上,CommandTimeout也不会引发异常。

最新更新