0

我在我的 VS2012 项目上运行了代码分析选项,它发现了以下内容;

CA1001 拥有一次性字段的类型应该是一次性在“DataGridViewColumnSelector”上实现 IDisposable,因为它会创建以下 IDisposable 类型的成员:“CheckedListBox”、“ToolStripDropDown”。如果“DataGridViewColumnSelector”之前已发布,则将实现 IDisposable 的新成员添加到此类型被视为对现有使用者的重大更改。DataGridColSelector DataGridViewColumnSelector.cs

我让我的类 DataGridViewColumnSelector 从 IDisposable 继承,我想知道在 dispose 方法中放什么

更新 :

这是我的尝试。自从我把课程密封起来后,代码分析就不再抱怨了。我仍然不确定我是否“做对了”

    public sealed class DataGridViewColumnSelector  :IDisposable 
{
    private DataGridView mDataGridView = null;
    private CheckedListBox mCheckedListBox;
    private ToolStripDropDown mPopup;

    public delegate void CustomRightClickDelegate(object sender, MouseEventArgs e);

    public event CustomRightClickDelegate GridRightClickEvent;
    /// <summary>
    /// The max height of the popup
    /// </summary>
    public int MaxHeight = 300;
    /// <summary>
    /// The width of the popup
    /// </summary>
    public int Width = 200;

    public DataGridView DataGridView
    {
        get { return this.mDataGridView; }
        set
        {
            if (this.mDataGridView != null) this.mDataGridView.MouseDown -= this.mDataGridView_MouseDown;
            this.mDataGridView = value;
            if (this.mDataGridView != null) this.mDataGridView.MouseDown += this.mDataGridView_MouseDown;
        }
    }



    void mDataGridView_MouseDown(object sender, MouseEventArgs  e)
    {
        if (e.Button == MouseButtons.Right)
        { 

            if( this.mDataGridView.HitTest(e.X, e.Y).Type == DataGridViewHitTestType.ColumnHeader)
            {
                this.mCheckedListBox.Items.Clear();
                foreach (DataGridViewColumn c in this.mDataGridView.Columns)
                {
                    this.mCheckedListBox.Items.Add(c.HeaderText, c.Visible);
                }
                int PreferredHeight = (this.mCheckedListBox.Items.Count*20);
                this.mCheckedListBox.Height = (PreferredHeight < this.MaxHeight) ? PreferredHeight : this.MaxHeight;
                this.mCheckedListBox.Width = this.Width;
                this.mPopup.Show(this.mDataGridView.PointToScreen(new Point(e.X, e.Y)));
            }
            else
            {
                if (this.GridRightClickEvent != null)
                {
                    this.GridRightClickEvent.Invoke(sender, e);
                }

            }
        }
    }

    public DataGridViewColumnSelector()
    {
        this.mCheckedListBox = new CheckedListBox();
        this.mCheckedListBox.CheckOnClick = true;
        this.mCheckedListBox.ItemCheck += new ItemCheckEventHandler(this.mCheckedListBox_ItemCheck);

        ToolStripControlHost mControlHost = new ToolStripControlHost(this.mCheckedListBox);
        mControlHost.Padding = Padding.Empty;
        mControlHost.Margin = Padding.Empty;
        mControlHost.AutoSize = false;

        this.mPopup = new ToolStripDropDown();
        this.mPopup.Padding = Padding.Empty;
        this.mPopup.Items.Add(mControlHost);
    }

    public DataGridViewColumnSelector(DataGridView dgv)
        : this()
    {
        this.DataGridView = dgv;
    }

    void mCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
    {
        this.mDataGridView.Columns[e.Index].Visible = (e.NewValue == CheckState.Checked);
    }

    public void Dispose()
    {
        //http://stackoverflow.com/questions/6826958/c-toolstripdropdown-doesnt-dispose-destroyhandle
        // http://msdn.microsoft.com/en-au/library/b1yfkh5e%28v=vs.71%29.aspx 
        // Kirsten says I dont feel sure about what I am doing here.

        mCheckedListBox.Dispose(  );
        mPopup.Dispose(  );
        GC.SuppressFinalize(this);

    }
}
4

1 回答 1

1

你应该调用 dispose 然后你的表单被处理。

还。您的实施IDisposable缺少一些重要的东西。

1)您应该确保没有订阅您的自定义事件的事件。这最终可能会给您的应用程序带来内存泄漏。

//in dispose
GridRightClickEvent = null

2) MSDN有一个实现的最佳实践IDisposable

public sealed class DataGridViewColumnSelector  : IDisposable
{
  //removed: ~DataGridViewColumnSelector  (){ Dispose(false); /*destructor*/ }

  //class context omitted

  public void Dispose()
  {
     Dispose(true);
     GC.SuppressFinalize(this);
  }

  private void Dispose(bool disposing)
  {
    if(disposing)
    {
      //kill the reference - do not dispose the object. 
      //it was *not* created here, os it should *not* be disposed here
      mDataGridView = null; 

      //makes sure no outside object has a reference
      //to the event - thus keeping it alive when it should be garbagecollected
      GridRightClickEvent = null; 

      if(mCheckedListBox != null) mCheckedListBox.Dispose();

      if(mPopup != null) mPopup.Dispose();

      if(mControlHost  != null) mControlHost .Dispose();

    }
  }
}
于 2013-04-22T08:08:59.723 回答