处置或不处置(CA2000)

我在旧项目上开启代码分析。 我可以理解的大多数评论的结果,但是CA2000:在丢失范围之前处理对象很难找到正确的答案。

例如,来自ASP.Net页面的这段代码:

private void BuildTable()
{
    HtmlTableRow tr = new HtmlTableRow();
    HtmlTableCell td = new HtmlTableCell();

    tr.Cells.Add(td);
    // add some controls to 'td'

    theTable.Rows.Insert(0, tr);
    // 'theTable' is an HtmlTable control on the page
}

给CA提供消息:

CA2000:Microsoft.Reliability:在方法'BuildTable()'中,在对象'tr'上的所有引用超出范围之前调用System.IDisposable.Dispose。

CA2000:Microsoft.Reliability:在方法'BuildTable()'中,对象'td'不会沿着所有异常路径放置。 调用System.IDisposable.Dispose对象'td'之前,所有对它的引用超出范围。 (以及有关添加到'td'的控件的类似消息。)

我可以解决第二个问题:

private void BuildTable()
{
    HtmlTableRow tr = new HtmlTableRow();
    HtmlTableCell td = new HtmlTableCell();

    try
    {
        tr.Cells.Add(td);
        // add some controls to 'td'

        td = null; // this line is only reached when there were no exceptions
    }
    finally
    {
        // only dispose if there were problems ('exception path')
        if (td != null) td.Dispose();
    }

    theTable.Rows.Insert(0, tr);
}

但我不认为有可能解决关于'tr'的信息。 我不能解释这一点,因为方法退出后仍然需要。

或者我错过了什么?

顺便说一句:改变这种theTable.Rows.InserttheTable.Rows.Add改变CA消息“沿着所有的异常路径没有设置”


代码分析无法完全理解您的代码,只是警告您是否创建了一个似乎不被处置的可丢弃对象。 在你的情况下,你应该关闭警告,因为在离开方法之前不应该丢弃该对象。 您可以通过自定义代码分析规则集或在每个有此警告的方法显示代码分析错误的地方关闭整个项目的警告。

也就是说,我建议您在处理IDisposable对象时使用using构造:

using (var tr = new HtmlTableRow()) {
  using (var td = new HtmlTableCell()) {
    tr.Cells.Add(td);
    theTable.Rows.Insert(0, tr);
  }
}

除了这个代码是无稽之谈,因为你不想处理刚添加到表中的行和单元格。


我认为你刚才已经证明CA2000规则在大多数代码库中并不是非常有用据我所知,

  • 在HtmlTableRow上处理除非它在UI设计器内部使用,否则没有任何用处; 我从来没有见过任何人在Asp.net控件上调用dispose。 (Winforms / WPF是另一种情况)
  • 你在表格中存储对td的引用,所以你不应该放弃它。
  • 由于两个以上的是在正常的代码很常见的,我没有看到CA2000规则是有价值的大部分代码库-有这么多的误报你很可能在1 50例错过当它是一个真正的问题。


    此代码将摆脱这两个警告(我用一个使用(HtmlTable)来模拟您的全球HtmlTable成员...):

    using (HtmlTable theTable = new HtmlTable())
    {
        HtmlTableRow tr = null;
        try
        {
            HtmlTableCell td = null;
    
            try
            {
                td = new HtmlTableCell();
    
                // add some controls to 'td'
    
    
                tr = new HtmlTableRow();
                tr.Cells.Add(td);
    
                /* td will now be disposed by tr.Dispose() */
                td = null;
            }
            finally
            {
                if (td != null)
                {
                    td.Dispose();
                    td = null;
                }
            }
    
            theTable.Rows.Insert(0, tr);
    
            /* tr will now be disposed by theTable.Dispose() */
            tr = null;
        }
        finally
        {
            if (tr != null)
            {
                tr.Dispose();
                tr = null;
            }
        }
    }
    

    但我认为你会考虑使用一种使用子功能来使代码更清晰的方法:

        private static void createTable()
        {
            using (HtmlTable theTable = new HtmlTable())
            {
                createRows(theTable);
            }
        }
    
        private static void createRows(HtmlTable theTable)
        {
            HtmlTableRow tr = null;
            try
            {
                tr = new HtmlTableRow();
                createCells(tr);
    
                theTable.Rows.Insert(0, tr);
    
                /* tr will now be disposed by theTable.Dispose() */
                tr = null;
            }
            finally
            {
                if (tr != null)
                {
                    tr.Dispose();
                    tr = null;
                }
            }
        }
    
        private static void createCells(HtmlTableRow tr)
        {
            HtmlTableCell td = null;
    
            try
            {
                td = new HtmlTableCell();
    
                // add some controls to 'td'
    
    
                tr.Cells.Add(td);
    
                /* td will now be disposed by tr.Dispose() */
                td = null;
            }
            finally
            {
                if (td != null)
                {
                    td.Dispose();
                    td = null;
                }
            }
        }
    
    链接地址: http://www.djcxy.com/p/63007.html

    上一篇: To Dispose or not to Dispose (CA2000)

    下一篇: Scheduled task with windows services and system.timer.timer