2010-06-30 141 views
10

我在VS做一些ASP.NET开发,刚刚发现了一个有趣的小代码建议(我认为他们来自coderush,但我可能是错的)。为什么我需要调用ASP.NET控件上的dispose?

每当我创建控件时,它告诉我应该为他们使用“使用”语句。尽管我对这里发生了什么感到困惑。与使用我的代码看起来是这样的:

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的处理。但是,MSDN库中的文档说:

Dispose方法使控制 处于不可用状态。在调用 这种方法后,您必须释放对控件的所有 引用,以便它占用的内存可以是 垃圾回收回收。

所以我希望我现在有一个不可用的对象在我的控制结构中,所以它会打破或不呈现或什么。然而,一切似乎都很好。

所以我想知道为什么所有的控件都是一次性的?这是否仅仅是因为它们中的一部分会使它们成为一次性意味着一个调用在顶层处理的调用可以递归地传递给所有子控件?

我想我会理解,如果不是因为文档明确指出处置控件使其无法使用......文档是否错误?

+0

如果我们不使用“使用”块,我们如何处理孤立的对象(@Toby提到)? – Lijo 2012-11-21 17:38:27

回答

14

你不应该这样做。你需要做的是确保listingTable在Controls集合中,以便它在页面被丢弃时被丢弃。然后,listingTable对象负责正确处理其所有子项。

这就是为什么所有的Control对象实现IDisposable接口。这样,每个父母控制器都可以在其所有孩子上调用Dispose,而无需先测试/投射每个孩子。每个控件都独自负责确定在调用Dispose方法时是否确实有任何需要清理的内容。

该文档没有错。如果在处置过程期间实现IDisposable 并且具有实际被清理的状态数据的任何正确编写的对象应该抛出ObjectDisposedException,如果它的任何公共/受保护/内部属性或方法在处置后被访问。 (在调用Dispose之后假设无效状态)。如果某些类型实际上没有任何清理内容,则不会理会这个规则,也不必担心无效状态。

原因你得到一个建议,把它包在using块,因为分析器没有意识到listingTable将出售其Rows收集,这将配置每个已添加到它的行对象。此外,如果在HtmlTableRow tableRow = new HtmlTableRow()listingTable.Rows.Add(tableRow)之间抛出异常,则HtmlTableRow对象将是“孤立”的,并且不在任何其他对象的IDisposable层次结构中。代码分析希望你使用try/finally块来立即处置HtmlTableRow,如果发生这种情况。

+1

谢谢。我对这个问题大部分都有怀疑,但是对于在这里发生的事情有更详细的了解。我甚至不考虑控制的“孤立”。 – Chris 2010-06-30 16:09:32

+0

如果我们不使用“使用”块,我们如何处理'孤立的对象? – Lijo 2012-11-21 17:04:24

+0

@Lijo:使用try/finally块 – Toby 2013-01-31 16:32:40

相关问题