由于SqlConnection
和SqlCommand
实现了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
也不会引发异常。