Is it really an error to override events in C#? - c#

I read in this question: Overriding Events in VB
It is even an error to override events in C#. The C# Programming Guide says:
Do not declare virtual events in a base class and override them in a derived class. The C# compiler does not handle these correctly in Microsoft Visual Studio 2008 and it is unpredictable whether a subscriber to the derived event will actually be subscribing to the base class event.
I wonder why a framework class breaks this rule, or even why the compiler allows it.
I can't understand why it's a mistake to override events. Sure an inheriting class can always monitor the base class event and take it's own actions afterwards, but what if it wants to ensure that it is the first event observer to see the event? What it it wants to decide to swallow the event under certain conditions? What's wrong with doing something like this:
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
VerifyActiveCountMatches();
base.OnCollectionChanged(e);
InvokePropertyChanged("Count");
}

It's not an error to do so - but it may well be a bad design decision. There's a big difference; the compiler won't let you get away with an error, but it rarely criticizes your design.
The code you've shown for OnCollectionChanged does not override an event - it overrides the method which raises the event. That's an entirely different matter. An event is something like:
// "Field-like" event - the compiler implements the add/remove and
// creates a backing field.
public event EventHandler Click;
or
// Manually-implemented event; you write the add/remove yourself, and
// create a separate backing variable if necessary.
public event EventHandler Click
{
add { ... }
remove { ... }
}
These are the pieces of code which handle the subscription and unsubscription - and it's these that the advice is saying you shouldn't override. You'd rarely want to, and as the quoted text says, there are plenty of situations where it wouldn't do what you wanted it to anyway.

That is not overriding the event, you are overriding the event invoker there (possibly a handler, but that pattern usually denotes a protected member that is used to invoke the event handler).
Overriding an event would look something like:
public override event EventHandler CollectionChanged;

I'm quoting this blog:
"Using a virtual field-like event in the parent class and not changing any of its behavior in the overriding derived class is not necessary. You can simply omit the override in the derived class to get the desired behavior."
If you aren't changing behavior then why make it virtual? As pointed out, this is different than overriding the method that raises the event.

Related

virtual and normal event of the same name in the same class

I'm not an absolute beginner, but this one is seemingly beyond me (or maybe I'm out of energy at the end of the day here :)). What is the following code piece trying to achieve (taken from this SO post)?
public class ObservableStack<T> : Stack<T>, INotifyCollectionChanged, INotifyPropertyChanged
{
//...
protected virtual event PropertyChangedEventHandler PropertyChanged;
//...
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
add { this.PropertyChanged += value; }
remove { this.PropertyChanged -= value; }
}
}
I need to translate this to VB.NET, which doesn't seem to be happy with the existence of two PropertyChanged events. Which one needs to be removed while still implementing the interface correctly?
There are two ways to do this in VB. First, and easiest, is to get rid of the explicit implementation of INotifyPropertyChanged. Make the protected event public, and don't use the explicit one with the add/remove blocks.
However, it happens that ObservableCollection<T> implements INotifyPropertyChanged explicitly itself, so there may be some good reason to do that. Ordinarily I do whatever the framework does, because historically their ideas are, on average, better than mine. In this case I don't know why they did it that way, but at the very worst it can't hurt.
And it turns out you can implement interfaces explicitly in VB.NET. In theory. But I tried doing something based on this Lovecraftian example code here, and gave up in horror and despair.
I think you'll be fine just implementing the interface regularly.

extending control - use sender or this

I am extending a control's capabilities. I want to know if there are any advantages in using a casted sender vs this keyword in an event. For example:
public class CustomTextBox : TextBox
{
public CustomTextBox()
{
Loaded += CustomTextBox_Loaded;
}
void CustomTextBox_Loaded(object sender, RoutedEventArgs e)
{
//use either
var c = (CustomTextBox)sender;
//or
var c2 = this;
//do whatever...
}
}
I believe using this might be more efficient (No casting necessary).
usually events are handled outside the class which publishes them, in the subscriber class. In such a setup, it may be desired to get the reference of publisher in subscriber & that is when type casting the sender to get the reference of publisher comes handy.
I agree, in my opinion, if you can get the reference of publisher without type casting thats better, you should use this.
But since you are extending a control, please check if its really necessary to use event of the base class. An event is for the outside world, and not for child classes.
If the event pattern has been implemented correctly in the base control class, I would expect a virtual method responsible for raising which you can override while extending the control, like this -
class CustomTextBox : TextBox
{
protected override void OnClick(EventArgs e)
{
//place your code here if you want to do the processing before the contol raises the event. Before call to base.OnClick(e);
base.OnClick(e); // call to base funciton fires event
//place your code here if you want to do the processing after the contol raises the event. After call to base.OnClick(e);
}
}
Hope it helps.
I doubt you would find any measurable performance difference either way, especially for an event like Loaded that is only going to be raised once during the lifetime of the control.
That said, it seems to me you should go ahead and use this, just because it's more convenient and expressive. If your method is already in the code of the class of the sender, why not? What possible gain could there be in code comprehension, ease of authoring, maintainability, or any other common goal in programming to using the sender parameter instead of just using this?

Why public event cannot be invoked outside directly?

Consider we have a class with event declared:
public class FooBar
{
public event EventHandler FooBarEvent;
}
Despite of "publicness" of the event, we cannot call FooBarEvent.Invoke from outside.
This is overcame by modyfing a class with the following approach:
public class FooBar
{
public event EventHandler FooBarEvent;
public void RaiseFooBarEvent(object sender, EventArgs eventArguments)
{
FooBarEvent.Invoke(sender, eventArguments);
}
}
Why accessing public events outside is limited by adding and removing listeners only?
Defining a public event merely gives consumers the ability to subscribe and unsubscribe from it. The ability to raise the event is limited to the type hierarchy which declares the event.
Allowing all subscribers to also be able to raise the event would be a bit chaotic. Imagine for example I had a TextBox class which had a Focused event. If any old consumer could raise the event then the Focused event could easily fire when the TextBox class wasn't actually focused. This would make it nearly impossible to maintain any type of invariant during an event.
Personally I think this is done to properly convey the design principles behind the whole events architecture.
The purpose of an event is to notify a listener of said event occurring in a given object.
What's the point of raising events of classes that don't belong to you?
That's what events are for. If you want to invoke it publicly you probably need delegates not events
Events gives encapsulation,
It prevents other classes from assigning anything to it
It prevents passing it as a parameter to methods
It prevents assigning it to any variable
It prevents calling it from another classes (not even derived classes have access to it)
etc
public accessibility tells that it can be subscribed from anywhere, not invoked from anywhere.
the answer to your question is
An event in C# is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object.
Invoking the event from outside doesn't makes sense therefore it is not allowed.
I think you should change your perspective on how events work. Other classes shouldn't "own" the event and trigger it. Classes which "listen" to the event by "subscribing" to it and do a certain action when this event occurs.
That's the way the language is defined - an event can only be fired by the owning class. If you must fire it from a different class, have the owning class define a public method that will fire the event:
public FireFooBarEvent (object sender, EventArgs args)
{
if(FooBarEvent != null)
FooBarEvent(sender, args);
}
And call this method from any class.

Confused in Events & RelayCommand (C#)

I am a beginner in Events, trying to built a MVVM......
**Question 1:
Referring to some online example of overriding a ArrayList class with events:
http://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx
public delegate void ChangedEventHandler(object sender, EventArgs e);
public class ListWithChangedEvent: ArrayList
{
public event ChangedEventHandler Changed;
protected virtual void OnChanged(EventArgs e) {if (Changed != null) Changed(this, e);}
...
}
Am I correct to say that if I override any class by adding an event into it, whenever any member/method inside the overrided class was changed/called, the method OnChanged will be automatically run? (and I can see it when debugging?)
**Question 2:
Sorry quite confused with what is doing inside RelayCommand. Specifically why in the EventHandler CanExecuteChanged it Add and then Remove the method from the ConfigurationManager simultaneously?
Thanks in advance.
As for your 1st question, I think you misunderstand something; just adding a method called OnChanged does not have the effect you describe. As with any other method, it must be called by some other code to be executed. As the base class and its methods do not know anything about the derived class, they do not invoke the method/event - and not even "by convention" because it is named OnChange.
I'm not sure whether I understand your 2nd question correctly. The CanExecuteChanged event is used to notify the UI that something has changed that influences whether a command can or cannot be executed. I don't know your code or the sample you are referring to in regards to ConfigurationManager, but removing and adding an event handler is generally done in order to assert that an event handler is registered exactly once. If you register an event handler several times, it is called multiple times - a behavior one would rarely want. Therefore one removes the event handler before registering it anew.

Mixing enums with event classes in an event aggregator

I attempted to implement my own simple event aggregator recently. I got a lot of inspiration from the event aggregator article on MSDN. There is one thing that I notice about the event aggregator on MSDN is the events are actually classes on their own. This isn't really a bad thing at all. However, I just find it awkward to always create a new empty class for every single little event.
The reason I find it awkward is because of the need to create a class for every single granular event. A mouse click event, for instance, would have double_click, single_click, left_click, right_click, etc. And all of these are going to have a class of its own. It gets messy after a while.
So in my own implementation, I thought I could make it in such a way where the ClickEvent is a class, but all the granular events related to the Click event would then be "types" of the ClickEvent. In this case, the "types" are enum. The usage would look something like this:
//Publisher
eventAggregator.GetEvent<ClickEvent>.Publish(ClickEventType.Double_Click, eventArgs);
//Subscriber
eventAggregator.GetEvent<ClickEvent>.Subscribe(ClickEventType.Double_Click, handlerMethod);
However, I'm not sure if this implementation defeats the whole purpose of having a strongly typed event? Now, it seems like the ClickEvent is merely a container for the different event enum types.
Yes it does (seem like a container that is) - your handler will fire regardless of the click type and there will be some code required in the handler to determine the type of click, which makes things a little messier.
If your issue is mostly the organisation of the files/classes and keeping the code tidy, why not just create the click events as nested classes within a main click class
e.g.
public static class ClickEvents // Prevent instantiation
{
public class SingleLeft { }
public class SingleRight { }
public class DoubleLeft { }
public class DoubleRight { }
// Are there any more click events possible?!
}
eventAggregator.GetEvent<ClickEvents.SingleLeft>.Publish();
Aside from that, it's the uniqueness of the type that determines the event signature, and therefore multiple types are required to satisfy this particular implementation
At least the above keeps your handler code clean
void HandleLeftClick()
{
}
vs
void HandleClick(ClickArgs e)
{
if(e.ClickType == ClickType.Left)
{
}
}
Edit:
Also remember that you can subscribe multiple events to the same handler if you want to handle more than one click type:
eventAggregator.GetEvent<ClickEvents.SingleLeft>.Subscribe(HandlerMethod);
eventAggregator.GetEvent<ClickEvents.SingleRight>.Subscribe(HandlerMethod);
(this would work in the rare situation that the subscriber didn't care which mouse button was clicked)
I think you missed one possibility. You see, you don't have to create a new class for each notification. Instead, you are free to reuse classes but carry some additional state of arbitrary complexity inside.
public class MouseClickNotification {
public bool IsDoubleClick;
public MouseButton ClickedButton;
// any additional stuff
This way it is you who precisely define the granularity of your notification model.

Categories