Search code examples
c#objectdelegatesdestroy

destroying object doesn't remove delegate from invocation list


I have a little problem with my objects... I have an object with one delegate inside to which it subscribe in constructor. When I destroy this object the invocation list still tell me that it has one subscriber in. and when and create this object again I find two subscriber in (the old that I have destroyed and the new one). How can I solve this problem and remove the subscriber in the list cleanly?

Here is the code for test:(two button to destroy and create object inside)

public partial class Form1 : Form
{
    testdelegate thisdelegatetest;
    public Form1()
    {
        InitializeComponent();
        thisdelegatetest = new testdelegate();//create object 
        Timer mytimer = new Timer();//timer to see something BEGIN
        mytimer.Interval = 1000;
        mytimer.Tick += new EventHandler(mytimer_Tick);
        mytimer.Start();//timer to see something END
    }
    protected void mytimer_Tick(object sender, EventArgs e)
    {//each 1second look at the list invocation
        lb_IndelList.Text = "actual subscribers : " + testdelegate.dl_myfunctionthatcopy.GetInvocationList().Count().ToString();
    }
    private void DestroyObject_Click(object sender, EventArgs e)
    {//destroy object
    /*edit*/
        thisdelegatetest.Delete();
        thisdelegatetest = null;//dereferencing for GC
    /*edit*/
    }

    private void CreateObject_Click(object sender, EventArgs e)
    {//create object
        thisdelegatetest = new testdelegate();
    }

}
public class testdelegate
{
    public delegate void del_copysomething(int newvaluetocopy);
    internal static del_copysomething dl_myfunctionthatcopy;
    public int valueforallobject = 0;

    public testdelegate()//ctor
    {
        dl_myfunctionthatcopy += new del_copysomething(copythisint);
    }
    /*edit*/
    public void Delete()
    { 
        dl_myfunctionthatcopy -= new del_copysomething(copythisint);
    }
    /*edit*/
    private void copythisint(int newvalue)
    {
        valueforallobject = newvalue;
    }
}

Thanks for your help.


Solution

  • Since you cannot call the destructor manually, why not implementing the IDisposable interface and execute the unregistering in the Dispose method?=!

    public class testdelegate : IDisposable
    {
        public delegate void del_copysomething(int newvaluetocopy);
        internal static del_copysomething dl_myfunctionthatcopy;
        public int valueforallobject = 0;
    
        public testdelegate()//ctor
        {
            dl_myfunctionthatcopy += new del_copysomething(copythisint);
        }
        private void copythisint(int newvalue)
        {
            valueforallobject = newvalue;
            Console.WriteLine("Copied");
        }
    
        public void Dispose()
        {
            dl_myfunctionthatcopy -= new del_copysomething(copythisint);
            GC.SuppressFinalize(this);
        }
    }
    

    In the DestroyObject_Click method you would just call the Dispose method:

    private void DestroyObject_Click(object sender, EventArgs e)
    {   //call Dispose destroy object
        thisdelegatetest.Dispose();
    }