3

由于SqlConnectionSqlCommandimplement 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”。

为什么?

4

2 回答 2

3

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

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

于 2012-06-17T12:44:54.763 回答
1

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

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

于 2012-06-17T09:41:55.357 回答