471,337 Members | 941 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,337 software developers and data experts.

Adding same method twice to delegate

Maybe I'm going nuts, but I was so sure that adding the same method
more than once to a delegate would result in only one entry on the
delegate's call list:

this.UpdateEnd += new EventHandler(UpdateStockCode);
this.UpdateEnd += new EventHandler(UpdateStockCode);

if (this.UpdateEnd != null)
{
this.UpdateEnd(this, System.EventArgs.Empty);
}

would result in only one call to UpdateStockCode(). However, it results
in two.

How do I ensure that there is only ever one copy of the method on the
delegate list, so that the method is only called once? Do I have to do
this:

this.UpdateEnd -= new EventHandler(UpdateStockCode);
this.UpdateEnd += new EventHandler(UpdateStockCode);

this.UpdateEnd -= new EventHandler(UpdateStockCode);
this.UpdateEnd += new EventHandler(UpdateStockCode);

?

Dec 6 '05 #1
3 8084
Hi Bruce,

The documentation of Delegate.Combine and Delegate.Remove is very clear
about this. Also note that if you call Delegate.Remove, only the last
matched instance is removed.

You may add a method like this:
private void AddEvent(EventHandler handler)
{
// Only add if it does not already exist in the list
if (UpdateEnd == null || Array.IndexOf(UpdateEnd.GetInvocationList(),
handler) < 0)
{
UpdateEnd += handler;
}
}

And also take a look at the C# lang spec, you will see that you can
even "overload" the += op for your event, something like this:

private EventHandler updateEnd;
public event EventHandler UpdateEnd
{
add
{
if (updateEnd == null ||
Array.IndexOf(updateEnd.GetInvocationList(), value) < 0 )
{
updateEnd += value;
}
}

remove
{
updateEnd -= value;
}
}

Hope this helps,
Thi

Dec 6 '05 #2
Hi,

What if you really want to call the same method twice?

A better approach to your solution may be:

//you create one delegate once only
protected EventHandler UpdateEndMethod = new
EventHandler(UpdateStockCode);

//you can then do
this.UpdateEnd += UpdateEndMethod ;
this.UpdateEnd -= UpdateEndMethod ;
Maybe if you give more details about your particular situation a better
approach can be proposed.
cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation

"Bruce Wood" <br*******@canada.com> wrote in message
news:11**********************@g14g2000cwa.googlegr oups.com...
Maybe I'm going nuts, but I was so sure that adding the same method
more than once to a delegate would result in only one entry on the
delegate's call list:

this.UpdateEnd += new EventHandler(UpdateStockCode);
this.UpdateEnd += new EventHandler(UpdateStockCode);

if (this.UpdateEnd != null)
{
this.UpdateEnd(this, System.EventArgs.Empty);
}

would result in only one call to UpdateStockCode(). However, it results
in two.

How do I ensure that there is only ever one copy of the method on the
delegate list, so that the method is only called once? Do I have to do
this:

this.UpdateEnd -= new EventHandler(UpdateStockCode);
this.UpdateEnd += new EventHandler(UpdateStockCode);

this.UpdateEnd -= new EventHandler(UpdateStockCode);
this.UpdateEnd += new EventHandler(UpdateStockCode);

?

Dec 6 '05 #3
No, I never want to call the same method twice. In fact, the very
purpose of the event is to concentrate a bunch of other events into a
single invocation.

What I'm doing is using events to help me construct derived values
within a class. My class is a validator that accepts a database object
and then allows callers to change one field at a time. (It's the model
side of a maintenance screen.) When you load up a new business object
into the validator, that object might expose, say, properties A and B
(along with AChanged and BChanged events, etc.)

However, there may also be a derived property C that is calculated
based on A and B. Up until yesterday I was simply inserting code into
the "set" methods of A and B to recalculate C whenever either changed,
and raise the CChanged event accordingly. However, as the model became
more and more complicated, I started getting large numbers of events
(up to 7) for the same property, as the various properties upon which
it depended changed one by one and caused a recalculation of the
derived property. All of this several times over for several derived
properties. The process looked something like this (for the simple
example given):

this.A = something;
A's setter calls a method to recalculate C
Raise CChanged
Raise AChanged
this.B = something;
B's setter calls a method to recalculate C again
Raise CChanged
Raise BChanged

Essentially, the problem was that there was no way to tell the derived
properties to hold off recalculating themselves because a bunch of
things were about to change, and it would be better to wait until the
dust settled and recalculate then.

That's when I came up with the idea of using the xxxChanged events
within the model itself, and building a kind of BeginUpdate / EndUpdate
structure. So, now the process looks something like this:

this.AChanged += new EventHandler(RecalculateC);
this.BChanged += new EventHandler(RecalculateC);
....
BeginUpdate
this.A = something;
Raise AChanged
this.B = something;
Raise BChanged;
EndUpdate -> Raise UpdateEnded event
RecalculateC;
Raise CChanged;

and it all works because "RecalculateC" looks something like this:

private void RecalculateC(object sender, EventArgs e)
{
if (this.UpdateInProgress)
{
this.UpdateEnded -= new EventHandler(RecalculateC);
this.UpdateEnded += new EventHandler(RecalculateC);
}
else
{
... recalculate C and raise CChanged event ....
}
}

Of course, I need the "this.UpdateEnded -= new
EventHandler(RecalculateC);" line because otherwise "RecalculteC" will
be called twice, because "RecalculateC" was originally called twice
while the update was in progress in response to the AChanged and
BChanged events.

So, I need to play that little trick with the UpdateEnded event to get
the behaviour I want, which is "no matter how many times I'm called
while an update is in progress, I want to be invoked once when the
update ends."

Dec 6 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

5 posts views Thread by Ian Richardson | last post: by
reply views Thread by Cordell Lawrence | last post: by
4 posts views Thread by Edward Diener | last post: by
5 posts views Thread by Nathan Harmston | last post: by
reply views Thread by rosydwin | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.