Delegates specified as ref parameters and stored in second objects private fields

M

mortb

Why won't the third messagebox show in the second example, but not the
first?

cheers,
mortb

///////////////////////////////////////////////////////
///
/// Example 1
///

using System;
using System.Collections.Generic;
using System.Windows.Forms;

public delegate void myDel();

public class MyClass
{
public static void Main()
{
myDel del1 = delegate () { MessageBox.Show("1"); };
mySecondClass class2 = new mySecondClass(ref del1);
class2.addToDel();
class2.addToDel(ref del1);

del1();
}

}

public class mySecondClass
{
public mySecondClass(ref myDel del)
{
_del = del;
}

public void addToDel()
{
_del += delegate () { MessageBox.Show("2"); };
}

public void addToDel(ref myDel del)
{
del += delegate () { MessageBox.Show("3"); };
}

myDel _del;
}


///////////////////////////////////////////////////////
///
/// Example 2
///


public class MyClass2
{
public static void Main()
{
List<myDel> del1 = new List<myDel>();
del1.Add(delegate () { MessageBox.Show("1"); });
mySecondClass2 class2 = new mySecondClass2(ref del1);
class2.addToDel();
class2.addToDel(ref del1);

foreach(myDel step in del1)
{
step();
}
}


}

public class mySecondClass2
{
public mySecondClass2(ref List<myDel> del)
{
_del = del;
}

public void addToDel()
{
_del.Add(delegate () { MessageBox.Show("2"); });
}

public void addToDel(ref List<myDel> del)
{
del.Add(delegate () { MessageBox.Show("3"); });
}


List<myDel> _del;
}
 
M

mortb

Sorry I should have written:
Why *does* the third messagebox show in the second example, but not the
first?
 
M

Marc Gravell

Sorry for rushed explanation - am in hurry.

Unless I am mistaken...
The 3rd message box *does* show in the first example; the 2nd one doesn't.

You start with #1 in the invocation list.

The "ref" in the ctor does nothing; all you have is _del pointing to the
same delegate as del. When (in addToDel()) you use _del +=, you *reassign*
_del; _del and del are now pointing at different memory; _del now has one
more item in the invocation list (#1 and #2), but the original del is
unaffected.

In addToDel(ref del) you reassign del (keeping the change in the caller via
"ref"), getting a delegate including #1 and #3 to to the invocation list.

You then invoke the delegate that the caller knows. It knows nothing of the
_del field, so it can't see #2. It sees the instance with #1 and #3.

Perhaps you need to re-cap on what "ref" does?

Marc
 
M

Marc Gravell

For completeness, in the second example *none* of the "ref" modifiers do
anything. You have a single list, to which you add things. None of the
methods reassign the parameter, so "ref" is unnecessary.

Precisely *because* you have a single list, everything is in it. So it
works. But you are re-inventing the multicast-delegate here, and introducing
some interesting gotchas involving ownership (of the list), etc. Not a great
idea.

IMO, unless the design *really* warrants it, you should avoid too much
handling of delegates in this way. The event model works well, as ownership
and the subscription model is very well defined and understood, and the
multicast-delegate handles all the "list" aspects.

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top