为什么我需要在ASP.NET控件上调用dispose?

时间:2010-06-30 15:26:15

标签: asp.net controls dispose

我正在VS中进行一些ASP.NET开发,并且刚刚发现了一个有趣的小代码建议(我认为它们来自coderush,但我可能错了)。

每当我创建控件时,它都会告诉我我应该为它们使用“using”语句。我对这里发生的事情感到有点困惑。使用我的代码看起来像:

using (HtmlTableRow tableRow = new HtmlTableRow())
{
    tableRow.Attributes.Add("class", isOddRow ? "OddRow" : "EvenRow");
    listingTable.Rows.Add(tableRow);
    addCell(tableRow, row, "issueId");
    addCell(tableRow, row, "Title");
    addCell(tableRow, row, "Type");
    addCell(tableRow, row, "Summary");
}

所以我期待在using语句结束时它将在tableRow上调用dispose。但是,MSDN库中的文档说:

  

Dispose方法离开Control   处于无法使用的状态。打电话后   这个方法,你必须释放所有   引用控件所以   它占据的记忆力可以   通过垃圾收集回收。

所以我希望我现在在我的控制结构中有一个不可用的对象,所以它会破坏或不渲染或其他东西。但是,一切似乎都很好。

所以我想知道为什么所有控件都是一次性的?难道只是因为它们中的一部分并且使它们全部成为一次性意味着可以将一个处于最高级别的处理调用递归传递给所有子控件吗?

我想如果不是因为文档明确表示处理控件使其无法使用这一事实我会理解......文档是不是错了?

1 个答案:

答案 0 :(得分:14)

你不应该真的这样做。您需要做的是确保listingTable位于Controls集合中,以便在处置页面时将其处置。然后,listingTable对象负责正确处理其所有子节点。

这就是所有Control个对象实现IDisposable接口的原因。这样,每个父控件都可以在其所有子节点上调用Dispose,而无需先测试/转换每个子节点。每个控件都负责确定在调用Dispose方法时是否确实有任何需要清理的内容。

文档没有错。任何正确编写的对象实现IDisposable 并具有在dispose进程期间实际清理的状态数据如果任何public / protected / internal属性或方法被访问后应该抛出ObjectDisposedException处置。 (假设调用Dispose后的无效状态。)如果某些类型实际上没有任何要清理的东西,则会忽略此规则,并且不必担心无效状态。

您收到建议将其包装在using块中的原因是因为分析器没有意识到listingTable将处置其Rows集合,这将收集每个HtmlTableRow tableRow = new HtmlTableRow()集合已添加到其中的行对象。此外,如果在listingTable.Rows.Add(tableRow)IDisposable之间抛出异常,则HtmlTableRow对象将是“孤立的”,而不是在任何其他对象的HtmlTableRow层次结构中。如果发生这种情况,Code Analysis希望您使用try / finally块立即处理{{1}}。