First, let's say that the event I need to code will return a custome
EventArgs object, so I define that class as:
public class MyCustomEventArgs : EventArgs
{
public MyCustomEventArgs(string myCustomEventProperty)
{
this.myCustomEventProperty = myCustomEventProperty;
}
public string myCustomEventProperty;
}
Next, in the class that needs to expose this property, I first declare
a delegate for the event:
public delegate void MyEventHandler(object sender, MyCustomEventArgs
ce);
Next, I define the public event:
public event MyEventHandler MyEvent;
Next I declare a special method that any other method or event handler
in the class can use to raise the event:
protected virtual void OnMyEvent(string myCustomEventProperty)
{
MyCustomEventArgs ce = new MyCustomEventArgs(myCustomEventProperty);
if (this.MyEvent != null)
{
this.MyEvent(this, ce);
}
}
Now to raise the event I can:
this.OnMyEvent("a string value");
Now, my question is this. The OnMyEvent method is not realy required
to raise this event. I could just as easily have:
MyCustomEventArgs ce = new MyCustomEvent();
ce.myCustromEventProperty = "a string value";
if (this.MyEvent != null)
{
this.MyEvent(this, ce);
}
From what I can tell, the OnMyEvent method is only useful if the event
needs to ber raised in more than one place in the class.
Is this a correct assumption? Or is there a reason to use the
OnMyEvent method even if the event will only be raised once in the
class?
I also meant to ask, why is this OnMyEvent method a protected virtual
method?
> OK, based on my research and personal experiance, here is how I code
> events in C#.NET.
>
> First, let's say that the event I need to code will return a custome
> EventArgs object, so I define that class as:
>
> public class MyCustomEventArgs : EventArgs
> {
> public MyCustomEventArgs(string myCustomEventProperty)
> {
> this.myCustomEventProperty = myCustomEventProperty;
> }
> public string myCustomEventProperty;
> }
In general, you should make your public data an actual property, rather
than a public field.
Regardless, you should definitely _not_ name something a "Property" when
it's not an actual property.
> Next, in the class that needs to expose this property,
I assume "property" is a typo here, and you really meant "event".
> I first declare
> a delegate for the event:
>
> public delegate void MyEventHandler(object sender, MyCustomEventArgs ce);
FYI, as of .NET 2.0, you don't need to declare a delegate. You can just
use "EventHandler<MyCustomEventArgs>" instead.
> Next, I define the public event:
>
> public event MyEventHandler MyEvent;
>
> Next I declare a special method that any other method or event handler
> in the class can use to raise the event:
>
> protected virtual void OnMyEvent(string myCustomEventProperty)
> {
> MyCustomEventArgs ce = new MyCustomEventArgs(myCustomEventProperty);
>
> if (this.MyEvent != null)
> {
> this.MyEvent(this, ce);
> }
> }
Note that the above is not thread-safe. Strictly speaking, there's no
need to make it thread-safe if you know for sure you're always accessing
the event in just one thread. But, it's simple enough to make the method
thread safe, and the default implementation for an event is itself
thread-safe so I always like to just go ahead and follow that pattern.
A thread-safe version of your method looks like this:
protected virtual void OnMyEvent(string myCustomEventProperty)
{
EventHandler<MyCustomEventArgs> handler = MyEvent;
if (handler != null)
{
handler(this, new MyCustomEventArgs(myCustomEventProperty));
}
}
By copying the current event delegate before performing any operations
with it, you ensure that it can't change from non-null to null before you
actually try to invoke it.
Note that I also moved the allocation of the EventArgs sub-class. It's
wasteful to allocate it unless you actually need it. For some events,
they happen so frequently, and are so often not actually subscribed, this
could actually be significant.
> Now to raise the event I can:
>
> this.OnMyEvent("a string value");
>
> Now, my question is this. The OnMyEvent method is not realy required
> to raise this event. I could just as easily have:
>
> MyCustomEventArgs ce = new MyCustomEvent();
>
> ce.myCustromEventProperty = "a string value";
> if (this.MyEvent != null)
> {
> this.MyEvent(this, ce);
> }
I assume that "new MyCustomEvent()" is another typo. Based on your
example declaration, it should be "new MyCustomEventArgs("a string
value")" (i.e. you have the wrong class name, and your example class
doesn't have a parameterless constructor so you have to provide the
field's value, just as you did in your OnMyEvent() method).
> From what I can tell, the OnMyEvent method is only useful if the event
> needs to ber raised in more than one place in the class.
Isn't that true of any method? :)
Actually, I personally find it useful to encapsulate specific "atomic"
operations (where "atomic" is not in the threading sense, but just in the
"these statements all go together" sense) in individual methods.
It's true that for any collection of statements that would only appear
once in your program, in theory there's no "reuse" motivation for making
them a separate method. But a) it's hard to predict what lines of code
might wind up being reused in the future, and b) your code can be a lot
more readable if you put these kinds of groups of statements into their
own method (with a descriptive name, of course).
In other words, this really has absolutely nothing to do with events, and
everything to do with programming style and what's an appropriate choice
when deciding when to put some group of statements into their own method.
As for this:
On Fri, 02 Jan 2009 17:10:46 -0700, Joe Cool <joe...@home.net> wrote:
> I also meant to ask, why is this OnMyEvent method a protected virtual
> method?
The same reason any method might be "protected virtual". It's protected
so that any sub-class can also call it, and it's virtual so that any
sub-class can override it. It need not be either if you don't want it to
be.
Note that the main reason you see this pattern in the Control class is
that sub-class authors may want to control the order in which their event
handling logic is executed. In that scenario, you don't so much really
override the base implementation in the sense of replacing it, as you
simply add your own functionality, calling the base implementation either
before, after, or in the middle of your own functionality.
In that scenario, the override really becomes more an event handler
itself. In situations where you don't care what order your own
functionality is executed, you could just as easily subscribe to the event
rather than overriding the method that raises the event. There's a very
very tiny efficiency gain by overriding rather than subscribing to the
event, and a very very tiny code protection gain (overriding helps make
sure your functionality can't be removed from the event subscribers, by
the base class or some other code using reflection to get at the event).
Other than that, it's pretty much six of one, a half-dozen of the other.
Pete
> Note that the above is not thread-safe. Strictly speaking, there's no
> need to make it thread-safe if you know for sure you're always accessing
> the event in just one thread. But, it's simple enough to make the method
> thread safe, and the default implementation for an event is itself
> thread-safe so I always like to just go ahead and follow that pattern.
>
> A thread-safe version of your method looks like this:
>
> protected virtual void OnMyEvent(string myCustomEventProperty)
> {
> EventHandler<MyCustomEventArgs> handler = MyEvent;
>
> if (handler != null)
> {
> handler(this, new MyCustomEventArgs(myCustomEventProperty));
> }
> }
>
> By copying the current event delegate before performing any operations
> with it, you ensure that it can't change from non-null to null before you
> actually try to invoke it.
Cool! I saw that pattern somewhere and have been copying it ever since, but
I wasn't sure if it was a necessary thing to do or if the original writer
was just paranoid. An explanation of its usage makes me feel like I'm not
wasting my time anymore.
To Joe Cool: I know you were only giving sample code, but I certainly hope
that in your real code you don't actually have the word "event" anywhere in
your event name. It's silly and redundant, but unfortunately some people
actually put it in there.
Your 2nd question answers your first one. Not only does creating the
On..... method save you from duplicating code in your class "if" you invoke
the method from more than one place, but by marking it protected virtual
means 2 things
01: A descendant class is able to call OnMyEvent (due to "protected"),
whereas it is not possible to invoke the event from a descendant class.
02: A descendant class is able to override (due to "virtual") the method and
change the behaviour.
--
Pete
====
http://mrpmorris.blogspot.com
http://www.capableobjects.com - Think domain, not database
> 01: A descendant class is able to call OnMyEvent (due to "protected"),
> whereas it is not possible to invoke the event from a descendant class.
Did you mean "a non-descendant class" at the end?
Yeah, I just used those names to remove any ambiguity. I never
actually code an event witht the word "Event" in its name, nor do I
code properties with the word "Property" as part its name.