Is it OK to set state within Event Raising methods? - c#

I ran across this pattern in the code of a library I'm using. It sets state within the event raising method, but only if the event is not null.
protected virtual void OnMyEvent(EventArgs e)
{
if(MyEvent != null)
{
EnsureChildControls();
MyEvent(this,e);
}
}
Which means that the state is not set when overriding the method:
protected override void OnMyEvent(EventArgs e)
{
base.OnMyEvent(e);
Debug.Assert( /* Child controls ensured */); // This fails
}
but is only set when handling the event:
foo.MyEvent += (o, args) => Debug.Assert(/* Child controls ensured */); // This passes
Setting state within the if(MyEvent != null) seems like bad form, but I've checked the Event Design Guidelines and it doesn't mention this.
Do you think this code is incorrect? If so, why? (Reference to design guidelines would be helpful).
Edit for Context:
It's a Control, I'm trying to create subclass of it, and the state that it's setting is calling EnsureChildControls() conditionally based upon there being an event handler. I can call EnsureChildControls() myself, but I consider that something of a hack.

I doubt you'll find any guidelines on something like this. Guidelines are typically for extremely common occurrences (which I wouldn't consider this).
Regarding the practice itself: I don't see any problem with doing it this way.
For what it's worth, you can avoid if(MyEvent != null) if you use this:
// initialize with empty delegate so MyEvent will never == null
public event MyEventHandler MyEvent = delegate {};

This answer provides an MSDN quote that answers my question:
When should you override OnEvent as opposed to subscribing to the event when inheritting
The protected OnEventName method also
allows derived classes to override the
event without attaching a delegate to
it. A derived class must always call
the OnEventName method of the base
class to ensure that registered
delegates receive the event.

Related

ObservableDictionary event raiser

I'm studying some examples provided by Microsoft for win8 development. I opened BasicControls sample and noticed LayoutAwarePage class and more precisely ObservableDictionary class. Reading about implementing events and raising them I can't see who's responsible to raise MapChangedEventHandler event. Based on parameters I believe that private void InvokeMapChanged(CollectionChange change, K key) method do this. But according to MSDN we need to provide a protected method that begins with On which doesn't occur in ObservableDictionary.
So, who raises MapChangedEventHandler?
An event in a class can be raised from within the class without need of an additional method to that.
So, if MapChangedEventHandler is an event, it can be called from inside the class just by this:
if (MapChangedEventHandler != null)
MapChangedEventHandler( parameters );
The only motive I can see (I'm not an expert) to the existance of those OnWhatever methods is to allow raising events from outside the class, or from some derived class, since events can only be raised from inside the declaring class.
Those OnWhatever methods must be some good practice (not a rule, nor a compiler rule).
Maybe they also take care of some additional stuff together with raising the event.
If they are not provided, probably they are not meant to be called from outside or from a derived class.
By the way, the MapChangedEventHandler is not an event. It's a delegate.
Events can be of that type, but their names are independant.
Like this:
class TestClass
{
these are the events of the class:
public event MapChangedEventHandler SomeEvent1;
public event MapChangedEventHandler SomeEvent2;
public event MapChangedEventHandler SomeEvent3;
//now this method calls the events (events can only be raised from inside the class)
public void SomeMethod()
{
//do lots of stuff
if (SomeEvent1 != null) SomeEvent1(whatever arguments it takes);
//do other stuff
if (SomeEvent2 != null) SomeEvent2(another arguments);
}
//now, if you want to let derived classes to raise events...
protected void OnSomeEvent3(Same Parameters As MapChangedEventHandler)
{
if (SomeEvent3 != null) SomeEvent3(parameters);
}
}

Purpose of event invocators?

I was writing some C# code which uses events, and Resharper asked if I want to create an event invocator. It generated the following code:
LowFuel handler = lowFuel;
if (handler != null) handler();
Maybe I am missing something or a little rusty, but what is an event invocator? I know about the handler which is where the actual logic for the event will go.
Thanks
As the name implies, it's a method used to raise the event. It's usually better than directly invoking the delegate, for several reasons, because it checks whether the handler is null before trying to invoke it (so you don't need to check that every time you want to invoke the event).
Also, note that by default Resharper creates the event invocator as public and non virtual. IMHO it shouldn't be public, it usually doesn't make sense to invoke an event from outside the class that declares it. Also, it's often useful to make this method virtual, so you can override it in derived classes, rather than subscribe to the event of the base class. I always declare event invocators as follows:
protected virtual void OnFoo(FooEventArgs args)
{
var handler = Foo;
if (handler != null)
handler(this, args);
}
An event invocator (horrible term) is simply the code that invokes the event.
It's not 100% clear from your code example, but normally you'd declare LowFuel separately from the usage (in an interface perhaps) which is why you need to check it exists before calling it.

Action<T> vs delegate event

I have seen developers using the below codes quite alternatively. What is the exact difference between these, and which ones go by the standard? Are they same, as Action and Func<T> is a delegate as well:
public event Action<EmployeeEventAgs> OnLeave;
public void Leave()
{
OnLeave(new EmployeeEventAgs(this.ID));
}
VS
public delegate void GoOnLeave(EmployeeEventAgs e);
public event GoOnLeave OnLeave;
public void Leave()
{
OnLeave(new EmployeeEventAgs(this.ID));
}
Fwiw, neither example uses standard .NET conventions. The EventHandler<T> generic should declare the event:
public event EventHandler<EmployeeEventArgs> Leave;
The "On" prefix should be reserved for a protected method that raises the event:
protected virtual void OnLeave(EmployeeEventArgs e) {
var handler = Leave;
if (handler != null) handler(this, e);
}
You don't have to do it this way, but anybody will instantly recognize the pattern, understand your code and know how to use and customize it.
And it has the great advantage of not being forced to choose between a custom delegate declaration and Action<>, EventHandler<> is the best way. Which answers your question.
The following two lines of code are almost equivalent:
public event Action<EmployeeEventAgs> Leave;
compared to:
public event EventHandler<EmployeeEventAgs> Leave;
The difference is in the signature of the event handler method. If you use the first approach with the action, you could have:
public void LeaveHandler(EmployeeEventAgs e) { ... }
and then this:
obj.Leave += LeaveHandler;
With the second approach, the signature of the LeaveHandler needs to be different:
public void LeaveHandler(object sender, EmployeeEventAgs e) { ... }
It is very important to notice that in both cases the event keyword is used to declare the event member. An event member declared this way is not simply a field of the class, despite it looks as if it was. Instead, the compiler creates it as an event property1. The event properties are similar to regular properties, except that they do not have get or set accessors. The compiler allows them to be used only on the left side of a += and -= assignments (adding or removing an event handler). There is no way to overwrite the already assigned event handlers, or to invoke the event outside the class that declares it.
If the event keyword was missing in both examples, you could do the following operations with no error or warning:
obj.Leave = LeaveHandler;
which will erase any registered handlers and replace them withe the LeaveHandler.
In addition, you can also perform this call:
obj.Leave(new EmployeeEventAgs());
The two situations above are considered an anti-pattern, if you intend to create an event. An event should be invoked only by the owner object and should not allow for untraceable removal of subscribers. The event keyword is the .NET's programmatic construct that helps you stick with the correct use of events.
Having the above in mind, I believe many people stick to the EventHandler approach because it is more unlikely to use an EventHandler without the event keyword. Actions have wider scope of usage, they do not look as naturally when used as events. The latter is, of course, a personal opinion, as the event handler approach has probably become too hardwired in my own coding practices. Still, if actions are used properly, it is not a crime to use them for events.
1 An event property is what the compiler automatically generates when seeing code like this:
event EventHandler SomeEvent
It becomes roughly the same code as the following:
private EventHandler _someEvent; // notice the lack of the event keyword!
public event EventHandler SomeEvent
{
add { _someEvent += value; }
remove { _someEvent -= value; }
}
Event invocations which we write as this:
this.SomeEvent(sender, args);
are converted into this:
this._someEvent(sender, args);
Action<T> is exactly the same as delegate void ... (T t)
Func<T> is exactly the same as delegate T ... ()
Action is just a shortcut for the full delegate declaration.
public delegate void Action<T>(T obj)
http://msdn.microsoft.com/en-us/library/018hxwa8.aspx
Which one to use would depend on your organizations coding standards/style.
Yes, Action and Func are simply convenience delegates that have been defined in the 3.5 clr.
Action, Func and lambdas are all just syntactical sugar and convenience for using delegates.
There is nothing magic about them. Several people have written simple 2.0 addon libraries to add this functionality to 2.0 code.
You may want to look here, seeing what the compiler actually generates for Action is the best description. There's no functional difference in what you wrote, just shorter, more convenient syntax.
In general, they are equivalent. But in the context of using a delegate for the type of an event, the convention is to use EventHandler (where T inherits EventArgs):
public event EventHandler<EmployeeEventArgs> Left;
public void Leave()
{
OnLeft(this.ID);
}
protected virtual void OnLeft(int id)
{
if (Left != null) {
Left(new EmployeeEventArgs(id));
}
}
You could have written these Action and Func generic delegates yourself, but since they're generally useful they wrote them for you and stuck them in .Net libraries.

What is the preferred method for event handling in C#?

Which is the preferred/recommended way of handling events in .NET:
this.Load += new EventHandler(Form1_Load);
private void Form1_Load(object sender, EventArgs e)
{ }
or
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
}
What would the pros/cons of each method be? I've used both methods over the years, and have usually leaned more towards the first method simply because that is what Visual Studio creates automatically for handling events. Are there any benefits to the second method that I am missing though?
The first way is what Microsoft suggests. The pattern is:
some code wants to raise an event, calls OnXxx
OnXxx makes a call to the delegate
Wired event handlers are called
If you perform the second model, you risk forgetting the base.OnXxx call and breaking everything. Nice part of option 2 is that you get to decide if you are called before or after all of the other event handlers. If you put your code before the base.OnXxx, you get executed before the event does. Of course the first model can be used always, the second only if you are subclassing the class raising the event.
It depends entirely on where you want to catch the event and why.
The first method (wire-up) is for when you want some other class to handle the event. And you may need to do that for a number of reasons; the other class may have access to services that perform some complex logic or whatever. The point is that you use the first method when you want a separate observer to respond to the event.
The second method (overriding) is for when you want the form to respond because it can; because it's responsibility is local.
Though not the original question, I want to point out that:
this.Load += new EventHandler(Form1_Load);
can be written as:
this.Load += Form1_Load;
The delegate construction is inferred.
There is no hard & fast rule but there are gotchas with both the approaches. You select one you can avoid easily.
Delegates
lot of developers place the += code in a place where it can get called repeatedly. At least lot of novices do that. As a result there will be 'n' entries in the delegate list maintained by the owner control and all of them get called. Simple way to avoid is to place the += calls in constructor kind of place which get called only once.
OnXXXX
The risk is with forgetting to call the base.XXX methods. This has been a common source of bugs and most Windows programmers are aware of the problems if you miss to call the base class versions - this is particular for the case of Windows messages (paint etc).
The overridden method is preferrable as it will be invoked polymorphically virtually by the CLR.
[Edit] Here is why I believe the overridden method is preferable:
Here is a simple example:
class Foo
{
public event EventHandler Changed = delegate { };
protected virtual void OnChanged()
{
this.Changed(this, EventArgs.Empty);
}
}
class Bar : Foo
{
public Bar()
{
this.Changed += new EventHandler(this.Bar_Changed);
}
void Bar_Changed(Object sender, EventArgs e) { }
}
class Baz : Foo
{
protected override void OnChanged()
{
base.OnChanged();
}
}
Now I believe the Baz is the better implementation and here is why. Bar must do the following IL instructions to wire up the event:
L_000a: ldftn instance void Bar::Bar_Changed(object, class [mscorlib]System.EventArgs)
L_0010: newobj instance void [mscorlib]System.EventHandler::.ctor(object, native int)
L_0015: call instance void Foo::add_Changed(class [mscorlib]System.EventHandler)
We must create a delegate to the handling method, an instance of the EventHandler and then call the add_Changed method on the event in the base class. While these are not performance killers none of the previous code is required for Baz to work. Since any call to OnChanged will be virtual the only performance penalty will be the CLR finding the right instance method to call in the inheritance chain.

When should you override OnEvent as opposed to subscribing to the event when inheritting

When should one do the following?
class Foo : Control
{
protected override void OnClick(EventArgs e)
{
// new code here
}
}
As opposed to this?
class Foo : Control
{
public Foo()
{
this.Click += new EventHandler(Clicked);
}
private void Clicked(object sender, EventArgs e)
{
// code
}
}
Overriding rather than attaching a delegate will result in more efficient code, so it is generally recommended that you always do this where possible. For more information see this MSDN article. Here is a pertinent quote:
The protected OnEventName method also
allows derived classes to override the
event without attaching a delegate to
it. A derived class must always call
the OnEventName method of the base
class to ensure that registered
delegates receive the event.
The event is for external subscribers. When you are deriving some control, always override the OnEvent method instead of subscribing to the event. This way, you can be sure when your code is called, because the actual event is fired when you call base.OnEvent(), and you can call this before your code, after your code, in the middle of your code or not at all. You can then also react on return values from the event (i.e. changed properties in the EventArgs object).
Be aware that (at least in .NET 2.0) I have found a few places in the framework (specifically in the DataTable class) where the OnFoo method is only called when the corresponding Foo event has been handled! This contravenes the framework design guidelines but we're stuck with it.
I've gotten around it by handling the event with a dummy handler somewhere in the class, eg:
public class MyDataTable : DataTable
{
public override void EndInit()
{
base.EndInit();
this.TableNewRow += delegate(object sender, DataTableNewRowEventArgs e) { };
}
protected override void OnTableNewRow(DataTableNewRowEventArgs e)
{
base.OnTableNewRow(e);
// your code here
}
}
Subscribing to the event is intended for a control to monitor events on a different control. For monitoring your own event OnClick is fine. Note, however, that Control.OnClick handles firing those subscribed events, so be sure to call it in your override.
If you override like Kent Boogaart comments you'll need to be carefull to call back base.OnClick to allow event suscriptions to be called
An inherited class should never subscribe to it's own events, or it's base class' events.
Now, if a class has an instance of another, different, class in it, then it can consume that class' events, and determine if it should raise it's own event or not.
For example, I rolled out a MRU List class recently. In it, there was a number of ToolStripMenuItem controls, whose click event I consumed. After that click event was consumed, I then raised my class's event. (see that source code here)
It is worth noting that there are some corner cases where it only works with handlers and not with OnEvent overrides. One such example-
Why style is not applied when I'm removing StartupUri in WPF?

Categories

Resources