0
votes

I have following code with three CA2000 warnings. For cellFirst variable, I could overcome this by using a “using” block. But for other two headercells, the controls are getting created in a helper function.

CA2000 : Microsoft.Reliability : In method GetTableCell(string, int, string, string), object 'lnkHide' is not disposed along all exception paths. Call System.IDisposable.Dispose on object 'lnkHide' before all references to it are out of scope.

CA2000 : Microsoft.Reliability : In method GetTableCell(string, int, string, string), object 'ltlText' is not disposed along all exception paths. Call System.IDisposable.Dispose on object 'ltlText' before all references to it are out of scope.

CA2000 : Microsoft.Reliability : In method GetTableCell(string, int, string, string), object 'newCell' is not disposed along all exception paths. Call System.IDisposable.Dispose on object 'newCell' before all references to it are out of scope.

CODE

    protected void grdTransactions_RowCreated(object sender, GridViewRowEventArgs e)
    {

        if (e != null)
        {
            if (e.Row.RowType == DataControlRowType.Header)
            {
                GridViewRow newHeaderRow = null;
                try
                {

                    newHeaderRow = new GridViewRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal);

                    using (TableHeaderCell cellFirst = new TableHeaderCell())
                    {
                        cellFirst.ColumnSpan = 1;
                        cellFirst.Text = "FIRST";
                        newHeaderRow.Cells.Add(cellFirst);
                    }


                    //Associate 
                    #region Associate

                    TableHeaderCell cellAssociate = GetTableCell("tableColGroupAssociate", 4, "associateHide", "Associate Transaction Info");

                    #endregion

                    //Financial 
                    #region Financial

                    TableHeaderCell cellFinancial = GetTableCell("tableColGroupTransaction", 5, "financialHide", "Financial Transaction Info");


                    #endregion

                    newHeaderRow.Cells.Add(cellAssociate);
                    newHeaderRow.Cells.Add(cellFinancial);
                    ((GridView)sender).Controls[0].Controls.AddAt(0, newHeaderRow);

                }
                finally
                {
                    if (newHeaderRow != null)
                    {
                        newHeaderRow.Dispose();
                        newHeaderRow = null;
                    }
                }

            }
        }




    }

    private static TableHeaderCell GetTableCell(string cssClassName, int colSpan, string hideClassName, string displayName)
    {
        TableHeaderCell newCell = new TableHeaderCell();
        newCell.ColumnSpan = colSpan;
        newCell.CssClass = cssClassName;

        LiteralControl ltlText = new LiteralControl();
        ltlText.Text = displayName;
        newCell.Controls.Add(ltlText);

        HyperLink lnkHide = new HyperLink();
        lnkHide.Text = SupportToolUIResource.HideLinkText;
        lnkHide.CssClass = hideClassName;
        lnkHide.Target = SupportToolUIResource.HideLinkTarget;
        newCell.Controls.Add(lnkHide);

        return newCell;
    }

REFERENCE:

  1. To Dispose or not to Dispose (CA2000)

UPDATED CODE

Used using block to overcome warning

  using (TableHeaderCell cellAssociate = new TableHeaderCell())
                    {
                        GetTableCell(cellAssociate,"tableColGroupAssociate", 4, "associateHide", "Associate Transaction Info");
                        newHeaderRow.Cells.Add(cellAssociate);
                    }


     private static void GetTableCell(TableHeaderCell cellAssociate, string cssClassName, int colSpan, string hideClassName, string displayName)
    {
        cellAssociate.ColumnSpan = colSpan;
        cellAssociate.CssClass = cssClassName;

        using (LiteralControl ltlText = new LiteralControl())
        {
            ltlText.Text = displayName;
            cellAssociate.Controls.Add(ltlText);
        }

        using (HyperLink lnkHide = new HyperLink())
        {
            lnkHide.Text = SupportToolUIResource.HideLinkText;
            lnkHide.CssClass = hideClassName;
            lnkHide.Target = SupportToolUIResource.HideLinkTarget;
            cellAssociate.Controls.Add(lnkHide);
        }


    }

QUESTION

Is there any pitfall in the application "using" block (as shown in the updated code) to overcome the warning?

1
Same answer as the accepted to the question you've linked. It's a warning based on a heuristic; suppress it if you are sure you're right.AakashM
FxCop is chronically unable to understand the way controls are disposed. It is getting you into trouble, you'll need to delete the finally block and get rid of the using statement. The cells are automatically disposed when the GridView is disposed. The GridView is automatically disposed when its parent is disposed. Etcetera. Later, well after this method stopped running.Hans Passant
@HansPassant Is there any pitfall in the application "using" block (as shown in the updated code) to overcome the warning?LCJ
@Lijo yes there is, absolutely DON'T do that. CA2000 is only applicable for objects that your code controls the lifetime of - since you give all the objects you create to the GridView, it is not your responsibility to Dispose them.AakashM

1 Answers

0
votes

Please read What’s wrong with use of “Using” block on Webcontrols? for getting some insight on this. Also refer Why would I need to call dispose on ASP.NET Controls?

Some points of interest are (from the above post):

  1. What we need to do is make sure that new controls are added is in the Controls’ collection so that it will be disposed when the Page is disposed.
  2. Control objects implement the IDisposable interface. Each parent control can call Dispose on all of its children
  3. Any properly-written object that implements IDisposable and has state data that is actually cleaned up during the dispose process should throw an ObjectDisposedException if any of its public/protected/internal properties or methods are accessed after it has been disposed. (Assume invalid state after Dispose has been called.) Some types will ignore this rule if they don't actually have anything to clean up, and don't have to worry about invalid state.