Maybe a stupid question, but..
In my code I use the following construction at several places.
void MyFunction()
{
DoSomething(myClass.myProperty)
myClass.PropertyChanged += (s,e ) => {
if (e.PropertyName == "myProperty") {
DoSomething(myClass.myProperty);
}
}
}
So I want to do something initially, and also do the same when the property changes in the future.
Now the thing is, MyFunction() gets called several time during my program's execution. Will the delegate I assign to PropertyChanged be added evertime it passes through this method? (consuming more memory every iteration and slowing down the program) Or is the compiler/runtime smart enough to understand I should be only added the first time..? And if so, how does this work?
The compiler can't know your intent ... it will faithfully attach the event handler on each call to MyFunction().
Look at it this way - they compiler can't know that the reference variables (e.g. myclass) in your function refer to the same instances of objects you've attached handlers to previously. Nor can it know that you haven't detached the handler somewhere else between calls. It can't make assumptions like this.
You, however, could restructure your code so that the handler is only attached once. Since other consumers may subscribe to the PropertyChanged event, you need to keep some independent state around to know whether you have subscribed or not. For example:
if( !haveSubscribedToPropertyChanged ) {
myClass.PropertyChanged += (s,e ) => {
if (e.PropertyName == "myProperty") {
DoSomething(myClass.myProperty);
}
}
haveSubscribedToPropertyChanged = true;
}
Many of the other answers suggest that you should check whether the PropertyChanged event is null to prevent adding several listeners. A problem with that solution is that PropertyChanged can be non-null if other parts of the code listens to the same event but for another property, like this.
void AnotherFunction()
{
myClass.PropertyChanged += (s,e) => {
if (e.PropertyName == "anotherProperty") {
DoSomethingElse(myClass.anotherProperty);
}
}
}
A better solution, in my opinion, would be to maintain a boolean flag which is initially false, and only set to true when MyFunction is called. Then, check this flag whether you need to add the event handler.
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.
Before I reinvent the wheel...
This is just an EXAMPLE for describing the problem -- let's say you have a backend with collection of some data, and frontend which displays one item of the collection.
At the backend I have ItemIndex -- whenever it changes, it fires up OnScroll event.
I also have AddNewItem method, it adds new item at the end of the collection. The end of the method is calling OnNewItem event handler.
And here is the catch -- in AddNewItem I have to change ItemIndex, which fires OnScroll. One of the receivers of both (!) OnScroll and OnNewItem if frontend which displays selected item.
In such case it is called twice (not good). One solution would be altering item_index instead of ItemIndex, and this way preventing OnScroll, but I don't like it because ItemIndex does not act as black box anymore.
Is there any established pattern for sequential firing events, and sending only "important" ones (here: OnNewItem overrides OnScroll)? My idea would be to define an event scope, then instead of sending events directly, just register them for sending, and at the close of scope sort them and send the required ones.
In general -- question -- how should I deal with potential sequential event triggering. Use internals to avoid sending redundant events? Ignore the overhead? ...?
The answer seems obvious to me athough I could have easily missed something:
private bool IsAdding { get; set; }
private int item_index;
private IList m_collection;
public void AddNewItem(object item)
{
if (item == null)
{
throw new Exception("Cannot add null item."); // little bit of contracting never hurts
}
m_collection.Add(item);
IsAdding = true;
ItemIndex = collection.Count - 1; //I'm just making assumptions about this piece but it is not important how you decide what your index is to answer the question
if (OnNewItem != null)
{
OnNewItem(this, EventArgs.Empty);
}
}
public int ItemIndex
{
get { return item_index =; }
set
{
item_index = value;
if (!IsAdding && OnScroll != null) //won't double fire event thanks to IsAdding
{
OnScroll(this, EventArgs.Empty);
}
IsAdding = false; //need to reset it
}
}
One thing I would note is that you made mention of just simply altering item_index directly but that wouldn't have a blackbox behavior. Well black box is all well and good ... but that term only applies to objects interacting with this class we have been discussing.
You should feel empowered to use the internals of your class within itself. It is not good OOP to blackbox items within itself. If you are doing that then your class probably has design issues where it should be split into multiple classes.
One solution is to use a 'latch' of some form. When updating, you perform your UI actions via a helper which sets a flag saying 'hey, I'm in a special state!'. Then, when raising events, you check to see if the latch is set -- if it is, you skip raising those events.
It's basically a very simple, generalised version of what Matthew posted. Depending on the situation, setting a flag may be more than adequate.
Jeremy Miller's explanation is worth reading
You could point both events at a single function. The function can determine the sender and perform the appropriate action(s).
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();
}
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.