Why would a 'public event EventHandler cccc' be null?
I have a class that's
public class Builder
{
public event EventHandler StartedWorking;
public Builder()
{
// Constructor does some stuff
}
public void Start()
{
StartedWorking(this, eventargobject); //StartedWorking is null --
}
}
This seems straightforward and something I do all the time? Am I missing something obvious or is there something that could cause this?
EDIT:
Does this mean that if I fire an event that is not subscribed to in a client class I have to check that it is not null?
EDIT-2:
I guess I'd never had events that were never not subscribed to and hence never ran into this --
You learn something new every day
Sorry about the seemingly stupid question....
The event handler will be null unless somebody has subscribed to the event. As soon as a delegate is subscribed to the event, it will no longer be null.
This is why it's always suggested to use the following form for raising events:
public void Start()
{
var handler = this.StartedWorking;
if (handler != null)
{
handler(this, eventArgObject);
}
}
This protects you from a null exception if there has been no subscribers.
As others have already said, it's null because there are no subscribers.
To answer your edit: Yes, you should always check an event for null before triggering it. However, if you just do a plain if(StartedWorking != null){...} you risk a race condition, because it's possible for a subscriber to unsubscribe after the null check but before you trigger the event. Because of this, you should always use this pattern when checking events for null:
protected void OnStartedWorking()
{
EventHandler localEvent = StartedWorking
if(localEvent != null)
{
localEvent(this, EventArgs.Empty);
}
}
This prevents the race condition by taking a copy of the event first so the subscribe list is fixed at the point of copying.
There's more infomration about publishing events on MSDN: How to Publish Events that Conform to .NET Framework Guidelines
(This works because in .net the MultiCastDelegate class in imutable, so any attempt to change the subscriber list on the event won't effect the copy you have made)
If you haven't hooked any event subscribers up to your StartedWorking event, then it will be null. That is how .NET events works.
This article, among other things, demonstrates that you should check for null before invoking an event. This other question and answer demonstrates how you can create events in a way that avoids the null check (basically by adding an empty handler always).
Don't you need to assign a function ?
StartedWorking += new EventHandler(afunction);
void afunction(object sender, EventArgs e)
{
DoSomething();
}
Related
I am in the phase of testing the project and I am dealing with a problem with attaching an event handler multiple times to the button.
I have a class with the _btnSelecteProj field, which I assign the button reference via the parameter in the InitProjects method.
Public Void InitProjects (Button btnSelectProject)
{
_btnSelecteProj = btnSelectProject;
_btnSelecteProj.MouseClick += BtnSelectProj_MouseClick;
}
This method is in the runtime called several times and therefore the event handler is assigned multiple times, which I need to prevent.
I realize that this a wrong design. However, it is not possible to refactor the whole project, because I am in a testing phase. I struggle with this problem in several places in the code.
I tried to prevent this problem this way:
_btnSelectedProj.MouseClick -= BtnSelectProj_MouseClick;
_btnSelectedProj.MouseClick += BtnSelectProj_MouseClick;
But it doesn't work.
I appreciate any advice.
In your event you can implement the add/remove operations as explicit methods and check you event handler for null in add.
For example you can check if the value of _btnSelecteProj is changed
public void InitProjects(Button btnSelectProject)
{
if (_btnSelecteProj != null)
{
if (_btnSelecteProj.Equals(btnSelectProject))
return;
_btnSelecteProj.MouseClick -= BtnSelecteProj_MouseClick;
}
_btnSelecteProj = btnSelectProject;
_btnSelecteProj.MouseClick += BtnSelecteProj_MouseClick;
}
I had to add method ClearEventHandlers() and remove event handler proper way.
public void ClearEventHandlers()
{
_btnSelecteProj.MouseClick -= BtnSelectProj_MouseClick;
}
This method runs at the end of the object's life-time.
NOTE: I'm not sure whether this question/answer is useful to someone else...
I have a C# class which introduce a new custom event type, and allows users add or remove listeners to it. Also I implement a method which revoves all event listeners during dispatch;
public event EventHandler DataCommited;
private void DetatchListeners()
{
if (DataCommited != null)
{
foreach (EventHandler eh in DataCommited.GetInvocationList())
{
DataCommited -= eh;
}
}
}
It is possible to implement a method which will be taking DataCommited event as an argument. So, I can unsign a set of events using one method. I tried a lot ways implementing it, but unfortunately failed to do it. I wonder if it is actually possible and how. Thank you!!!
It is possible to implement a method which will be taking DataCommited event as an argument.
Well, not really. You can take an EventInfo, but that's all. It's important to understand that this statement:
public event EventHandler DataCommited;
actually creates two things:
An event, which code in other classes can subscribe to and unsubscribe from
A field of type EventHandler, which you can use to call the handlers, or get each one individually.
A simpler implementation of your current code would simply be this:
public event EventHandler DataCommited;
private void DetatchListeners()
{
DataCommitted = null;
}
Unsubscribing from a field-like event just changes the value of the field, after all.
However, if you have an EventInfo, you don't know how that event is implement. It may be backed directly by a field - it might not be... there's no general way of asking an event for its current handlers, or setting a new list of handlers. All you can do directly with an event is subscribe and unsubscribe.
If you only use field-like events, you could use reflection to find the name of the field and set the value to null. You can't do it in general though.
See my article on delegates and events for more information.
my previos question is how to clear event handles in c#
Now i need to know that how to check any event handler already assigned?
If the event is in the same class where you will do the check, you can compare to null. But if this is not the case, you should ask yourself why do you care about the inside workings of a class. I mean it is the job of the class which contains the event to care about its subscribers not the opposite. But if you really want this information, the event containing class can expose a property for the outside world - like HasEventHandlers.
Unless I misunderstand the question, a simple check for null should be sufficient. You always need to check for a null in the event handler anyway before calling any event handlers.
In quick watch window I found the btnSubmit click handler with the following expression:
(((System.Web.UI.Control)(btnSubmit)).Events.head.handler).Method
An old solution presented by Jon Skeet where you explicitly implemented event handling would be the best way to address this.
Here is how:
private EventHandler m_myEvent;
public event EventHandler OnEvent
{
add
{
// First try to remove the handler, then re-add it
m_myEvent -= value;
m_myEvent += value;
}
remove
{
m_myEvent -= value;
}
}
In the unlikely scenario that you have multicast delegates, you could experience odd behaviors.
-- If I define an event with an inital empty delegate I don't need to check for null
class MyClass
{
public event EventHandler<MyEventArgs> MyEvent = delegate { };
void SomeMethod()
{
...
MyEvent(); // No need to check for null
...
}
}
-- Otherwise I need to check for null
class MyClass
{
public event EventHandler<MyEventArgs> MyEvent;
void SomeMethod()
{
...
if (MyEvent != null) // No need to check for null
MyEvent();
...
}
}
What's the difference between these? In what cases one is better than another?
Thanks
The upvoted answer is dramatically wrong, I have to post an answer. Somebody is wrong on the Internet, can't come to bed just yet.
It is convenient but it doesn't come for free. The compiler has to generate a class for the anonymous method and the JIT compiler has to generate code for it. And that code always executes when you raise the event, whether or not a client has subscribed an event handler. The null check code also always executes, but that takes a lot less code and time.
This isn't a lot of code and a lot of time. The null check takes 2 machine code instructions and should execute in a single CPU cycle. The anonymous delegate takes about an order of magnitude more but that's still not a lot on a modern machine. Personally, I'm too old to be wasteful like that, two invariably is my choice.
Not in the least because that's the standard pattern, everybody recognizes it.
First one is applicable solution, but it has very very little performance penalty to call extra empty delegate.
Second solution is not thread safe (if it matters for you, of cause).
You should use following:
var handler = MyEvent;
if (handler != null )
handler(this, new MyEventArgs());
At our company we wrote an extension method which hooks onto most events, and checks if it's null before invoking.
We reduced this:
var handler = MyEvent;
if (handler != null)
{
handler(...);
}
to
MyEvent.SafeTrigger(...);
Evil or not evil?
public static void Raise(this EventHandler handler, object sender, EventArgs args)
{
if (handler != null)
{
handler(sender, args);
}
}
// Usage:
MyButtonClicked.Raise(this, EventArgs.Empty);
// This works too! Evil?
EventHandler handler = null;
handler.Raise(this, EVentArgs.Empty);
Note that due to the nature of extension methods, MyButtonClicked.Raise will not throw a NullReferenceException if MyButtonClicked is null. (E.g. there are no listeners to MyButtonClicked event).
Evil or not?
Not evil. I wish events worked this way by default. Can someone explain why an event with no subscribers is null?
You can always declare your events like this (not that i recommend it):
public event EventHandler<EventArgs> OnClicked = delegate { };
That way they have something assigned to them when you call them, so they don't throw a null pointer exception.
You can probably get rid of the delegate keyword in C# 3.0...
Don't forget to use [MethodImpl(MethodImplOptions.NoInlining)], else its possible that it isn't thread safe.
(Read that somewhere long ago, remembered it, googled and found http://blog.quantumbitdesigns.com/tag/events/ )
Coming from a java background this has always seemed odd to me. I think that no one listening to an event is perfectly valid. Especially when listeners are added and removed dynamically.
To me this seems one of C#'s gottchas that causes bugs when people don't know / forget to check for null every time.
Hiding this implementation detail seems a good plan as it's not helping readability to check for nulls every single time. I'm sure the MSFTs will say there's a performance gain in not constucting the event if no one is listening, but imho it is vastly outweighed by the pointless null pointer exceptions / reduction in readability in most business code.
I'd also add these two methods to the class:
public static void Raise(this EventHandler handler, object sender)
{
Raise(handler, sender, EventArgs.Empty);
}
public static void Raise<TA>(this EventHandler<TA> handler, object sender, TA args)
where TA : EventArgs
{
if (handler != null)
{
handler(sender, args);
}
}
Why would it be evil?
Its purpose is clear: It raises the MyButtonClicked event.
It does add a function call overhead, but in .NET it will either be optimized away or pretty fast anyway.
It is slightly trivial, but it fixes my biggest complaint with C#.
On the whole, I think it's a fantastic idea, and will probably steal it.
I wouldn't say it's evil, but I'm interested in how your extension method fits in with the
protected virtual OnSomeEvent(EventArgs e){ }
pattern and how it handles extensibility via inheritance. Does it presume all subclasses will handle the event instead of override a method?
Although I wouldn't describ it as evil, it still has a negative implication, as it adds unnecessary overhead:
When calling
myEvent.Raise(this, new EventArgs());
the object EventArgs is initialized in all situations, even if no-one subscribed to myEvent.
When using
if (myEvent!= null) {
myEvent(this, new EventArgs());
}
EventArgs is only initialized if someone subscribed to myEvent.
Throwing an exception when there are no handlers is not really preferable by the most. If it does not have an handlers it is better to be empty rather than null.