2013-04-22 72 views
0

我在我的VS2012項目上運行了代碼分析選項,它發現了以下內容;那些擁有一次性場如何處理ToolStripDropDown?

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); 

    } 
} 
+0

這取決於你如何實現'IDisposable',以及如何往往你創建一個新的實例的最佳做法。試着展示你的代碼,以及你如何使用它。 – 2013-04-22 05:53:13

+0

你正在處理你的方法中的正確控制。我建議你在處理一個控件之前做一個空檢查,然後將它設置爲null(只是爲了確保GC確實認識到你不再需要這個對象)。如果你不需要它,不要GC會自動調用GC方法。 – wonko79 2013-04-22 07:02:58

回答

1

你shold調用dispose那麼你的形式處置。

另外。你的IDisposable的實現缺少一些重要的事情。

1)您應該確保沒有事件訂閱您的自定義事件。這可能最終會給你的應用程序一個內存泄漏。

//in dispose 
GridRightClickEvent = null 

2)MSDN有implemeting 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(); 

    } 
    } 
} 
+0

實現終結器(aka析構函數)不是最佳實踐。只有在類存儲非託管資源時才需要這樣做,這樣就不會像這樣的代碼那樣。產生這個錯誤的最強烈的指示是當Dispose(bool)方法在* disposing *爲false時沒有做任何有用的事情。就像在你的片段中一樣。 – 2013-04-22 10:50:53

+0

@HansPassant這使得sence。 我編輯了代碼exampel - 刪除析構函數 – 2013-04-22 11:12:10

+0

那麼下面//在這裏處理你的配置? 是不是 'GridRightClickEvent = null; mCheckedListBox.Dispose(); mPopup.Dispose();' – 2013-04-22 15:55:47