Is there any smart way to avoid the verbosity of testing the nullity on an event before calling it in a generic way ? It looks obvious that if I call a delegate, I want it to be assigned.
(If I Really want/need to test its nullity I could eventually do it explicitly, but putting this test systematically is kind of tedious and verbose.)
public delegate void ResetTradesDelegate();
public ResetTradesDelegate ResetTradesEvents;
public void OnSessionRxAdmMessage(IVfxFixAppSession session, FixMessage msg)
{
if (ResetTradesEvent != null) //<-- Is there "any" a way not to write this test explicitly for each delegate ?
ResetTradesEvent();
}
public event EventHandler NoDataEventHandler = delegate{};
Declaring an event in this way means it will never be null. It will always, at a minimum, have a single no-op event handler hooked up.
In your case, probably
public event ResetTradesDelegate ResetTradesEvents = delegate{};
Firing an event is always going to have a race condition associated with it. You're either going to risk trying to call a delegate when it's null, or calling a delegate after the event has been unhooked. Eric Lippert wrote a pretty comprehensive post on this topic here. The technique above still suffers from the second type of race condition, so the event handlers need to be robust to being called after the event has been unhooked.
static void CallIfNotNull(this Action action)
{
if (action != null) action();
}
As an extension method, this is quite convenient to use.
You can create your event-handler with an always-subscribed no-op event:
public class MyClass
{
public MyClass()
{
this.Event += (sender, e) => ();
}
public event EventHandler Event;
protected virtual void OnEvent()
{
this.Event(this, EventArgs.Empty);
}
}
However, this requires subscribing your event and will incur a performance penalty as the no-op delegate will still exist in the list of subscribed event handlers.
My preference here is to create a pair of extension methods to invoke any event handler, whilst performing a null-safe check:
public static void Raise(this EventHandler #event, object sender)
{
if(#event != null)
{
#event.Invoke(sender, EventArgs.Empty);
}
}
public static void Raise<TEventArgs>(
this EventHandler<TEventArgs> #event,
object sender,
TEventArgs args)
where TEventArgs : EventArgs
{
if(#event != null)
{
#event.Invoke(sender, args);
}
}
This can then be easily invoked anywhere in your library to safely raise the event:
this.ResetTradesEvent.Raise(this);
It's purely syntactic sugar; you're still doing the check on the delegate. It is however, a nice re-usable way to wrap up this smelly part of the C# language.
public static void Call(this Action action)
{
var safeAction = Interlocked.CompareExchange(ref action, null, null);
if (safeAction != null)
safeAction();
}
Using the null conditional operator keeps the test but is less verbose so works for me. I don't imagine it resolves the race condition that others have mentioned.
ResetTradesEvent?.Invoke();
This is suggested automatically in Visual Studio 2017.
Related
Is it possible to use Reflection is C# to fire an event? Say I have a situation like this:
public delegate void SomeEventHandler(object sender, BenArgs e);
class EventHub
{
public event SomeEventHandler SOME_EVENT;
public void fireEvent(String eventName)
{
SomeEventHandler evt = (SomeEventHandler) Delegate.CreateDelegate(typeof(SomeEventHandler), this, eventName);
evt.Invoke(null, null);
}
}
Meaning if I call
EventHub.fireEvent("SOME_EVENT")
then it makes the event hub fire SOME_EVENT? I've tried this and am just getting exceptions.
This is mostly a curiosity of mine, I know that in this case I could just as easily fire the event without reflection.
Assuming your current scenario, i.e.:
A field-like event.
The backing delegate-field has the same name as the event.
(this, EventArgs.Empty) are valid arguments to pass to the delegate.
You can do something like this (more argument validation required):
public void fireEvent(String eventName)
{
// Get a reference to the backing field
var del = (Delegate)typeof(EventHub)
.GetField(eventName, BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(this);
// Invoke the delegate, it's invocation-list will contain the listeners
if(del != null)
del.DynamicInvoke(this, EventArgs.Empty);
}
Usage:
var eHub = new EventHub();
eHub.SOME_EVENT += delegate { Console.WriteLine("SOME_EVENT fired.."); };
eHub.fireEvent("SOME_EVENT");
Now, you can generalize this idea with an extension method on object if you like, but all of this is a really bad idea. This problem can't be solved in the general case because one can't know how an event is "implemented." There could be arbitrary code inside the add and remove methods, and the logic to "fire" the event could also be just about anything. There might not even be a backing multicast delgate field to store the listeners.
In any case, trying to tell an object to fire an event is almost always a sign of a major design-flaw, IMO. If you still really do want this, it would be much better to declare a method like this in your class:
public void RaiseXXXEvent() { ... }
I'm a beginner in C# and having hard times understanding Events in C# .. The book i read (Illustrated C# 2008) gives an example about it , and there are few thing i need to ask about , so i will past the code here and point out the things i don't understand .
public class MyTimerClass
{
public event EventHandler Elapsed;
private void OnOneSecond(object source, EventArgs args)
{
if (Elapsed != null)
Elapsed(source, args);
}
}
class ClassA
{
public void TimerHandlerA(object obj, EventArgs e) // Event handler
{
Console.WriteLine("Class A handler called");
}
}
class ClassB
{
public static void TimerHandlerB(object obj, EventArgs e) // Static
{
Console.WriteLine("Class B handler called");
}
}
class Program
{
static void Main( )
{
ClassA ca = new ClassA(); // Create the class object.
MyTimerClass mc = new MyTimerClass(); // Create the timer object.
mc.Elapsed += ca.TimerHandlerA; // Add handler A -- instance.
mc.Elapsed += ClassB.TimerHandlerB; // Add handler B -- static.
Thread.Sleep(2250);
}
}
Ok, now the line after declaring the event here public event EventHandler Elapsed;
which is private void OnOneSecond(object source, EventArgs args) i know that the two line after it is to check if the event contains methods or not , but what is OnOneSecound for ? or when it's called ? or what it's named .. it's not event handler i guess right ? and what's the relationship between Elapsed and OnOneSecond ?
sorry for the newbie question .. and thanks in advance :)
the OnOneSecond method will be called internally by the MyTimerClass when it needs to invoke the event.
This is a common pattern used by most controls, including the microsoft ones.
Basically you dont need to be checking if the event is set in multiple places, you just do it in this one method then call this method internally to raise the event.
I tend not to pass the event args to the OnXXX method though, for example.
public event EventHandler<EventArgs> SomeEvent;
protected virtual void OnSomeEvent()
{
if (this.SomeEvent !=null)
{
this.SomeEvent.Invoke(this,EventArgs.Empty);
}
}
then to raise it
this.OnSomeEvent();
This is the method, that you call to raise the event safely.
the problem is, you can basically call
Elapsed(source, args)
but if there is noone connected to the event, this will raise a Reference Null exception. as the event is null, when nobody hears on it.
a better solution is, that you directly add a subscriber to the events. then you can safely call it directly. as there will be allways a subscriber.
public event Action<EventArgs> Elapsed = val => { };
(note that with the = its directly assigned. val => { } is a Lambda expression, that defines a empty subscriber.)
Also, look into the Reactive Framework for .net
if you want to do a lot of event stuff, this is the correct solution for it.
That allows you to manually fire the events from thein the class.
That is the standard pattern for raising internal events that's why it is private.
OnOneSecond is just a helper method defined to raise the event. You can use events without such methods, it is just an established pattern to wrap the if (Elapsed != null) check in a method with a name that starts with On...
Technically you could just use Elapsed(source, args) instead of OnOneSecond(source, args), but this will throw NullReferenceException if there are no listeners registered.
I am sure that I am just not understanding something fundamental about events and/or delegates in C#, but why can't I do the Boolean tests in this code sample:
public class UseSomeEventBase {
public delegate void SomeEventHandler(object sender, EventArgs e);
public event SomeEventHandler SomeEvent;
protected void OnSomeEvent(EventArgs e) {
// CANONICAL WAY TO TEST EVENT. OF COURSE, THIS WORKS.
if (SomeEvent != null) SomeEvent(this, e);
}
}
public class UseSomeEvent : UseSomeEventBase {
public bool IsSomeEventHandlerNull() {
// "LEFT HAND SIDE" COMPILER ERROR
return SomeEvent == null;
}
}
class Program {
static void Main(string[] args) {
var useSomeEvent = new UseSomeEvent();
useSomeEvent.SomeEvent +=new UseSomeEventBase.SomeEventHandler(FuncToHandle);
// "LEFT HAND SIDE" COMPILER ERROR
if (useSomeEvent.SomeEvent == null) {
}
var useSomeEventBase = new UseSomeEventBase();
useSomeEventBase.SomeEvent += new UseSomeEventBase.SomeEventHandler(FuncToHandle);
// "LEFT HAND SIDE" COMPILER ERROR
if (useSomeEventBase.SomeEvent == null) {
}
}
static void FuncToHandle(object sender, EventArgs e) { }
}
An event is really just an "add" operation and a "remove" operation. You can't get the value, you can't set the value, you can't call it - you can just subscribe a handler for the event (add) or unsubscribe one (remove). This is fine - it's encapsulation, plain and simple. It's up to the publisher to implement add/remove appropriately, but unless the publisher chooses to make the details available, subscribers can't modify or access the implementation-specific parts.
Field-like events in C# (where you don't specify the add/remove bits) hide this - they create a variable of a delegate type and an event. The event's add/remove implementations just use the variable to keep track of the subscribers.
Inside the class you refer to the variable (so you can get the currently subscribed delegates, execute them etc) and outside the class you refer to the event itself (so only have add/remove abilities).
The alternative to field-like events is where you explicitly implement the add/remove yourself, e.g.
private EventHandler clickHandler; // Normal private field
public event EventHandler Click
{
add
{
Console.WriteLine("New subscriber");
clickHandler += value;
}
remove
{
Console.WriteLine("Lost a subscriber");
clickHandler -= value;
}
}
See my article on events for more information.
Of course the event publisher can also make more information available - you could write a property like ClickHandlers to return the current multi-cast delegate, or HasClickHandlersto return whether there are any or not. That's not part of the core event model though.
You can easily use a very simple approach here to not repeatedly subscribe to an event.
Either of the 2 approaches below can be used:
Flag approach : _getWarehouseForVendorCompletedSubscribed is a private variable initialized to false.
if (!_getWarehouseForVendorCompletedSubscribed)
{
_serviceClient.GetWarehouseForVendorCompleted += new EventHandler<GetWarehouseForVendorCompletedEventArgs>(_serviceClient_GetWarehouseForVendorCompleted);
_getWarehouseForVendorCompletedSubscribed = true;
}
Unsubscribe Approach :Include an unsubscribe everytime you want to subscribe.
_serviceClient.GetWarehouseForVendorCompleted -= new
EventHandler<GetWarehouseForVendorCompletedEventArgs>
(_serviceClient_GetWarehouseForVendorCompleted);
_serviceClient.GetWarehouseForVendorCompleted += new
EventHandler<GetWarehouseForVendorCompletedEventArgs>
(_serviceClient_GetWarehouseForVendorCompleted);
Here the answer:
using System;
delegate void MyEventHandler();
class MyEvent
{
string s;
public event MyEventHandler SomeEvent;
// This is called to raise the event.
public void OnSomeEvent()
{
if (SomeEvent != null)
{
SomeEvent();
}
}
public string IsNull
{
get
{
if (SomeEvent != null)
return s = "The EventHandlerList is not NULL";
else return s = "The EventHandlerList is NULL"; ;
}
}
}
class EventDemo
{
// An event handler.
static void Handler()
{
Console.WriteLine("Event occurred");
}
static void Main()
{
MyEvent evt = new MyEvent();
// Add Handler() to the event list.
evt.SomeEvent += Handler;
// Raise the event.
//evt.OnSomeEvent();
evt.SomeEvent -= Handler;
Console.WriteLine(evt.IsNull);
Console.ReadKey();
}
}
Here's a slightly different question
What value is there in testing an externally defined event for null?
As an external consumer of an event you can only do 2 operations
Add a handler
Remove a handler
The null or non-nullness of the event has no bearing on these 2 actions. Why do you want to run a test which provides no perceivable value?
It's a rule in place when using the 'event' keyword. When you create an event, you are restricting outside class interaction with the delegate to a "subscribe / unsubscribe" relationship, this includes cases of inheritance. Remember an event is essentially a property, but for method calls, it isn't really an object itself, so really it looks more like this:
public event SomeEventHandler SomeEvent
{
add
{
//Add method call to delegate
}
remove
{
//Remove method call to delegate
}
}
You'd have to do that from the base class. That's the exact reason that you did this:
protected void OnSomeEvent(EventArgs e) {
// CANONICAL WAY TO TEST EVENT. OF COURSE, THIS WORKS.
if (SomeEvent != null) SomeEvent(this, e);
}
You can't access events from a derived class. Also, you should make that method virtual, so that it can be overridden in a derived class.
Publisher of the event implicitly overload only += and -= operations, and other operations are not implemented in the publisher because of the obvious reasons as explained above, such as don't want to give control to subscriber to change events.
If we want to validate if a particular event is subscribed in the subscriber class, better publisher will set a flag in its class when event is subscriber and clear the flag when it is unsubscriber.
If subscriber can access the flag of publisher, very easily identifiable whether the particular event is subscriber or not by checking the flag value.
Some text before the code so that the question summary isn't mangled.
class Tree
{
public event EventHandler MadeSound;
public void Fall() { MadeSound(this, new EventArgs()); }
static void Main(string[] args)
{
Tree oaky = new Tree();
oaky.Fall();
}
}
I haven't used events much in C#, but the fact that this would cause a NullRefEx seems weird. The EventHandler reference is considered null because it currently has no subsribers - but that doesn't mean that the event hasn't occurred, does it?
EventHandlers are differentiated from standard delegates by the event keyword. Why didn't the language designers set them up to fire silently in to the void when they have no subscribers? (I gather you can do this manually by explicitly adding an empty delegate).
Well, the canonical form is:
void OnMadeSound()
{
if (MadeSound != null)
{
MadeSound(this, new EventArgs());
}
}
public void Fall() { OnMadeSound(); }
which is very slightly faster that calling an empty delegate, so speed won out over programming convenience.
Another good way I've seen to get around this, without having to remember to check for null:
class Tree
{
public event EventHandler MadeSound = delegate {};
public void Fall() { MadeSound(this, new EventArgs()); }
static void Main(string[] args)
{
Tree oaky = new Tree();
oaky.Fall();
}
}
Note the anonymous delegate - probably a slight performance hit, so you have to figure out which method (check for null, or empty delegate) works best in your situation.
The recommended pattern is (.net 2.0+)
public class MyClass
{
public event EventHandler<EventArgs> MyEvent; // the event
// protected to allow subclasses to override what happens when event raised.
protected virtual void OnMyEvent(object sender, EventArgs e)
{
// prevent race condition by copying reference locally
EventHandler<EventArgs> localHandler = MyEvent;
if (localHandler != null)
{
localHandler(sender, e);
}
}
public void SomethingThatGeneratesEvent()
{
OnMyEvent(this, EventArgs.Empty);
}
}
I see a lot of recommendations for an empty delegate{} in an initializer, but I totally disagree with it. If you follow the above pattern you only check the event != null in one place. The empty delegate{} initializer is a waste because it's an extra call per event, it wastes memory, and it still can fail if MyEvent was set to null elsewhere in my class.
* If your class is sealed, you wouldn't make OnMyEvent() virtual.
You need to understand what your event declaration is actually doing. It's declaring both an event and a variable, When you refer to it within the class, you're just referring to the variable, which will be null when there are no subscribers.
Very Zen, eh?
You have to test for null when you want to raise an event:
protected void OnMyEvent()
{
if (this.MyEvent != null) this.MyEvent(this, EventArgs.Empty);
}
It would be nice if you didn't have to bother with this, but them's the breaks.
James provided a good technical reasoning, I would also like to add that I have seen people use this an advantage, if no subscribers are listening to an event, they will take action to log it in the code or something similar. A simpl example, but fitting in this context.
What is the point of raising an event if no one is listening? Technically, its just how C# chose to implement it.
In C#, an event is a delegate with some special feathers. A delegate in this case can be viewed as a linked list of function pointers (to handler methods of subscribers). When you 'fire the event' each function pointer is invoked in turn. Initially the delegate is a null object like anything else. When you do a += for the first subscribe action, Delegate.Combine is called which instantiates the list. (Calling null.Invoke() throws the null exception - when the event is fired.)
If you still feel that "it must not be", use a helper class EventsHelper as mentioned here with old and improved 'defensive event publishing' http://weblogs.asp.net/rosherove/articles/DefensiveEventPublishing.aspx
Using an extension method would be helpful in this scenario.
public static class EventExtension
{
public static void RaiseEvent<T>(this EventHandler<T> handler, object obj, T args) where T : EventArgs
{
if (handler != null)
{
handler(obj, args);
}
}
}
It can then be used like below.
public event EventHandler<YourEventArgs> YourEvent;
...
YourEvent.RaiseEvent(this, new YourEventArgs());
Thank you for the responses. I do understand why the NullReferenceException happens and how to get around it.
Gishu said
What is the point of raising an event if no one is listening?
Well, maybe it's a terminology thing. The appeal of an "event" system seems to me that all the responsibility of the fallout of the event that took place should be on the watchers and not the performer.
Perhaps a better thing to ask is: If a delegate field is declared with the event keyword in front of it, why doesn't the compiler translate all instances of:
MadeSound(this, EventArgs.Empty)
to
if (MadeSound != null) { MadeSound(this, EventArgs.Empty); }
behind the scenes in the same manner that other syntax shortcuts are? The number of boilerplate OnSomeEvent null checking methods that people have to write manually must be colossal.
I'm using C#, .NET 3.5. I understand how to utilize events, how to declare them in my class, how to hook them from somewhere else, etc. A contrived example:
public class MyList
{
private List<string> m_Strings = new List<string>();
public EventHandler<EventArgs> ElementAddedEvent;
public void Add(string value)
{
m_Strings.Add(value);
if (ElementAddedEvent != null)
ElementAddedEvent(value, EventArgs.Empty);
}
}
[TestClass]
public class TestMyList
{
private bool m_Fired = false;
[TestMethod]
public void TestEvents()
{
MyList tmp = new MyList();
tmp.ElementAddedEvent += new EventHandler<EventArgs>(Fired);
tmp.Add("test");
Assert.IsTrue(m_Fired);
}
private void Fired(object sender, EventArgs args)
{
m_Fired = true;
}
}
However, what I do not understand, is when one declares an event handler
public EventHandler<EventArgs> ElementAddedEvent;
It's never initialized - so what, exactly, is ElementAddedEvent? What does it point to? The following won't work, because the EventHandler is never initialized:
[TestClass]
public class TestMyList
{
private bool m_Fired = false;
[TestMethod]
public void TestEvents()
{
EventHandler<EventArgs> somethingHappend;
somethingHappend += new EventHandler<EventArgs>(Fired);
somethingHappend(this, EventArgs.Empty);
Assert.IsTrue(m_Fired);
}
private void Fired(object sender, EventArgs args)
{
m_Fired = true;
}
}
I notice that there is an EventHandler.CreateDelegate(...), but all the method signatures suggest this is only used for attaching Delegates to an already existing EventHandler through the typical ElementAddedEvent += new EventHandler(MyMethod).
I'm not sure if what I am trying to do will help... but ultimately I'd like to come up with an abstract parent DataContext in LINQ whose children can register which table Types they want "observed" so I can have events such as BeforeUpdate and AfterUpdate, but specific to types. Something like this:
public class BaseDataContext : DataContext
{
private static Dictionary<Type, Dictionary<ChangeAction, EventHandler>> m_ObservedTypes = new Dictionary<Type, Dictionary<ChangeAction, EventHandler>>();
public static void Observe(Type type)
{
if (m_ObservedTypes.ContainsKey(type) == false)
{
m_ObservedTypes.Add(type, new Dictionary<ChangeAction, EventHandler>());
EventHandler eventHandler = EventHandler.CreateDelegate(typeof(EventHandler), null, null) as EventHandler;
m_ObservedTypes[type].Add(ChangeAction.Insert, eventHandler);
eventHandler = EventHandler.CreateDelegate(typeof(EventHandler), null, null) as EventHandler;
m_ObservedTypes[type].Add(ChangeAction.Update, eventHandler);
eventHandler = EventHandler.CreateDelegate(typeof(EventHandler), null, null) as EventHandler;
m_ObservedTypes[type].Add(ChangeAction.Delete, eventHandler);
}
}
public static Dictionary<Type, Dictionary<ChangeAction, EventHandler>> Events
{
get { return m_ObservedTypes; }
}
}
public class MyClass
{
public MyClass()
{
BaseDataContext.Events[typeof(User)][ChangeAction.Update] += new EventHandler(OnUserUpdate);
}
public void OnUserUpdated(object sender, EventArgs args)
{
// do something
}
}
Thinking about this made me realize I don't really understand what's happening under the hod with events - and I would like to understand :)
I've written this up in a fair amount of detail in an article, but here's the summary, assuming you're reasonably happy with delegates themselves:
An event is just an "add" method and a "remove" method, in the same way that a property is really just a "get" method and a "set" method. (In fact, the CLI allows a "raise/fire" method as well, but C# never generates this.) Metadata describes the event with references to the methods.
When you declare a field-like event (like your ElementAddedEvent) the compiler generates the methods and a private field (of the same type as the delegate). Within the class, when you refer to ElementAddedEvent you're referring to the field. Outside the class, you're referring to the field.
When anyone subscribes to an event (with the += operator) that calls the add method. When they unsubscribe (with the -= operator) that calls the remove.
For field-like events, there's some synchronization but otherwise the add/remove just call Delegate.Combine/Remove to change the value of the auto-generated field. Both of these operations assign to the backing field - remember that delegates are immutable. In other words, the autogenerated code is very much like this:
// Backing field
// The underscores just make it simpler to see what's going on here.
// In the rest of your source code for this class, if you refer to
// ElementAddedEvent, you're really referring to this field.
private EventHandler<EventArgs> __ElementAddedEvent;
// Actual event
public EventHandler<EventArgs> ElementAddedEvent
{
add
{
lock(this)
{
// Equivalent to __ElementAddedEvent += value;
__ElementAddedEvent = Delegate.Combine(__ElementAddedEvent, value);
}
}
remove
{
lock(this)
{
// Equivalent to __ElementAddedEvent -= value;
__ElementAddedEvent = Delegate.Remove(__ElementAddedEvent, value);
}
}
}
The initial value of the generated field in your case is null - and it will always become null again if all subscribers are removed, as that is the behaviour of Delegate.Remove.
If you want a "no-op" handler to subscribe to your event, so as to avoid the nullity check, you can do:
public EventHandler<EventArgs> ElementAddedEvent = delegate {};
The delegate {} is just an anonymous method which doesn't care about its parameters and does nothing.
If there's anything that's still unclear, please ask and I'll try to help!
Under the hood, events are just delegates with special calling conventions. (For example, you don't have to check for nullity before raising an event.)
In pseudocode, Event.Invoke() breaks down like this:
If Event Has Listeners
Call each listener synchronously on this thread in arbitrary order.
Since events are multicast, they will have zero or more listeners, held in a collection. The CLR will loop through them, calling each in an arbitrary order.
One big caveat to remember is that event handlers execute in the same thread as the event is raised in. It's a common mental error to think of them as spawning a new thread. They do not.