“Dispose”方法是否会处理掉同一对象的所有类实例?

3

由于 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已经显示,这让我感到惊讶,因为它被处理了(disposed),但文本为“10”。为什么呢?

你的术语不清楚。“类的每个实例设置为相同的对象”没有意义。每个实例都与自身相同,每个对象也是如此。你将类实例(对象)与对它们的引用混淆了。您应该编辑您的问题以消除这种不明确性。 - user207421
@EJP 好的。如果不叫“实例”,那么commandtempCommand该怎么称呼? - ispiro
@ispiro - 变量。它们保存对实例的引用。 - Martin Smith
2个回答

3
通常,实现了IDisposable接口的对象(例如SqlConnection)这样做是因为它们需要在某个地方(如SQL服务器)代表其执行某些操作(如打开和维护连接),并将继续执行直到收到其他指令。通常,如果IDisposable对象要执行期望接收到的请求(如执行SQL操作),则需要让外部事物代表其执行操作。 Dispose方法的目的不是真正销毁调用它的对象,而是让对象知道由于没有其他人需要它,因此应该让正在代表其执行任何操作的外部实体知道他们不再需要这样做(例如,由于没有人会请求SqlConnection执行更多的请求,因此它不再需要保持与服务器的连接)。
如果在调用Dispose后,要求对象执行需要不再可用的外部实体的帮助,则最好让对象自己抛出ObjectDisposedException,而不是以其他方式失败。另一方面,如果可以完全不使用外部实体就可以执行某些操作,则经常适当这样做。使用IDisposable对象的代码通常应避免在Dispose之后使用未明确记录为可用的成员,并且应避免假设在一个类的一个版本上,在Dispose之后仍然有用的成员始终如此。尽管如此,在许多情况下,类指定特定成员可以在Dispose之后使用要比确保它们不能这样做更好。

1

它确实正确地处理了SqlCommand实例,而且无论你对它有多少引用,它们都指向同一个实例。

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


但如果它被处理了 - 它如何仍然记得“10”?(这不是默认值。) - ispiro
Dispose 用于释放非托管资源。在这种情况下,它是与 SQL Server 的连接以及可能不受 CLR 管理的任何其他内容。然而,CommandTimeout 很可能只是一个普通属性,在进行查询时使用,但在 SqlCommand 类中仅是一个 int 字段。因此,它不是非托管资源的一部分,而是垃圾回收器可以轻松清理的东西。更不用说 Dispose 没有办法清理单个 int - Joey
1
@ispiro - disposed 只是表示已调用 Dispose 方法,而不表示整个对象被消除。 - Martin Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接