There is a problem with this (one that there has been a debate about
recently). When you perform the check like this:
if( this.Click != null )
{
this.Click( this, EventArgs.Empty );
}
There could be a race condition between the checking of Click against
null, and the call to Click. In order to get around this, you should really
do this:
// Store the reference to the delegate.
EventHandler e = this.Click;
// Perform the check.
if (e != null)
// Fire.
e(this, EventArgs.Empty);
However, JIT can get in the way here. It can see that the local
variable is really just a reference to Click, and optimize it away, leaving
you with the original condition (checking Click directly, which you don't
want). You could get around this (forcing the copy to be performed) by
passing Click to a method that will invoke it (the reference will be copied
on the stack, and it will not be optimized away.
HOWEVER (yes, again), JIT can strike again, inlining the method into the
local code, and then optimizing the parameter out (it's just another value
on the call stack now, like a variable).
If that method is defined as virtual though, it can not be inlined, and
the reference will be copied, and nothing will happen. It won't work in
this case because the reference is never copied to a variable that is not
optimized away.
In order to get around this, there are a few solutions. One is to
assign a default delegate to the event that points to empty code. This way,
you never have to check against null, since you always know there will be
one event listener. The anonymous methods introduced in v2.0 makes this
easy, by allowing the following:
// The Click event.
public event EventHandler Click = delegate{};
Another way to get around this is to define the event as volatile (it
will be allowed in .NET 2.0).
A third way would be to have a standard method makes the calls to fire
the delegate (dynamically), which would circumvent the optimizations (by
being virtual, or ultimately calling something which is virtual that passes
the delegate in as well as the parameters).
Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
-
mv*@spam.guard.caspershouse.com
"Lee Alexander" <lee@NoSpamPlease_Digita.com> wrote in message
news:u6**************@TK2MSFTNGP10.phx.gbl...
Just to add, when creating general classes the pattern is to indirect the
call to the event with a protected virtual OnClick method that checks for
nullability (no one listening) of the Click event before raising it. This
helps derived classes to raise click event themeselves as they cannot
raise
the event directly. Making OnClick virtual also allows the derived class
to
intercept the event to do some work prior to any listeners recieving it:
public event EventHandler Click;
protected virtual void OnClick()
{
if( this.Click != null )
{
this.Click( this, EventArgs.Empty );
}
}
Events are raised by calling OnClick.
Regards
Lee
"Richard Blewett [DevelopMentor]" <ri******@develop.com> wrote in message
news:ez*************@TK2MSFTNGP11.phx.gbl... Say you have an event
public event EventHandler Click;
event handlers for the EventHandler type events have the signature
void MyHandler( object sender, EventArgs e);
so at the point you wanted to raise the event you write call the event
like a method ...
Click( this, EventArgs.Empty); // "this" is the sender and the event
args
is empty in this case
Regards
Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog
nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<1b****************************@phx.gbl>
hi all.
in vb.net i can write RaiseEvent.
can i do it in C# also?
how?
thanks - shachar.
---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.768 / Virus Database: 515 - Release Date: 22/09/2004
[microsoft.public.dotnet.languages.csharp]