代码之家  ›  专栏  ›  技术社区  ›  Chris

为什么需要对ASP.NET控件调用Dispose?

  •  10
  • Chris  · 技术社区  · 14 年前

    我在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方法离开控件 处于不可用状态。打电话后 这个方法,你必须释放所有 对控件的引用,因此 它占据的记忆可以是 垃圾回收。

    所以我希望在我的控制结构中有一个不可用的对象,这样它将中断或者不呈现或者其他什么。不过,一切似乎都正常。

    所以我想知道的是为什么所有的控制都是一次性的?仅仅是因为其中一些是可释放的并且使它们都是可释放的,这就意味着一个在顶级进行释放的调用可以递归地传递给所有子控件吗?

    我想如果不是因为文档明确地说处理控件会使其不可用,我会理解的…文件是不是错了?

    1 回复  |  直到 14 年前
        1
  •  14
  •   Toby    14 年前

    你不应该这么做。您需要做的是确保列表表在 Controls 集合,以便在释放页时释放它。然后,listingtable对象负责正确处理其所有子对象。

    这就是为什么所有 Control 对象实现IDisposable接口。这样每个父控件都可以调用 Dispose 在所有的孩子身上,不必先测试/铸造每一个。每个控件单独负责确定当其 处置 方法被调用。

    文件没有错。实现IDisposable的任何正确写入的对象 并具有在处理过程中实际清理的状态数据 如果在释放后访问了其任何公共/受保护/内部属性或方法,则应引发ObjectDisposedException。(之后假定无效状态 处置 一些类型将忽略此规则,如果它们实际上没有任何要清理的内容,并且不必担心无效状态。

    你得到建议的原因是 using 块是因为分析器没有意识到 listingTable 将处理其 Rows 集合,它将释放已添加到其中的每个行对象。此外,如果在 HtmlTableRow tableRow = new HtmlTableRow() listingTable.Rows.Add(tableRow) ,htmlTableRow对象将是“孤立的”,并且不在任何其他对象中 IDisposable 等级制度。代码分析希望使用try/finally块立即释放 HtmlTableRow 如果发生这种情况。