what does event inside the interface mean? - c#

I know the class implementing an interface must implement all its method. But what does event inside the interface mean?

It means that the type must implement the event - so that clients can subscribe to those events.
Think of events as pairs of methods (add/remove) just as properties have get/set. Just as you can have properties in interfaces, you can have events: the implementation has to provide the appropriate add/remove methods and the metadata to tie them to the event. In C# this can be done using field-like events:
public event EventHandler EventFromInterface;
or with explicit add/remove methods:
public event EventHandler EventFromInterface
{
add { ... }
remove { ... }
}

It means anything implementing that interface must raise that event. Pretty much the same as a Method or Property within an interface.

Related

Do events create instance of the assigned delegate or it's just a convention?

I've been recently learning 'events' and 'delegates' in C#.
Now I have a question that I didn't find the answer to, anywhere else.
As we all know every event is created based on a specific delegate. At first I thought that events are like delegate instances, but then I figured out that they are not.
My question here is that what is the relation between an event and its base delegate? does that event create an instance of the delegate and assign the 'event handler' methods to that at the runtime? or the assigned delegate is just a convention for assigning 'event handlers'?
An event is basically a list of methods to be invoked. Thus, delegate is nothing but kind of "strongly-typed" method reference. That is why there are exactly 2 possible operations on events: add handler += and remove handler: -=. That should prevent mistakes like accidental .Clear(), which will unsubscribe all existing listeners momentarily.
If you need more "obvious" example of how it works, than let the List<Delegate> be an event, where Delegate represents reference to a whatever function of a certain signature. Whenever you need to "invoke" event, you loop over existing list of delegates and simply invoke each one with the same parameter.
An event for a delegate is the same as aan auto-property for a backing-field. As an auto-property is just a wrapper around a backing-field an event is just a wrapper around a (backing) delegate. It provides an add- and a remove-method to append or remove event-handlers. So you have a private list of handlers and the event is just a wrapper to expose this list to the outside.
You can define an event as follows:
private EventHandler _explicitEvent;
public event EventHandler ExplicitEvent
{
add { _explicitEvent += value; }
remove { _explicitEvent -= value; }
}
So you have a private backing-field, which is a delegate. You can surely assign multiple handlers to the same delegate and thus to the event. In fact when you have an event as this:
public event EventHandler MyEvent;
the compiler will implicitely create the private backing-delegate for you, as it does for auto-properties also.
As for properties you can add some further logic within the add- and -remove-accessors in order to modify what happens when assigining an handler. You could make some validations for example or call some logging.
According to Microsoft Docs => Here
An event is a special kind of multicast delegate that can only be invoked from within the class that it is declared in. Client code subscribes to the event by providing a reference to a method that should be invoked when the event is fired. These methods are added to the delegate's invocation list through event accessors.
So, the answer would be: Yes. Events are basically a special type of multicast delegate.

Add events using Extension methods

I have found several posts about Raising events with an extension method, however my question is a bit different:
I have an interface like this:
public interface IStateMachine
{
void SetState(IState NewState);
IState GetState();
}
Using this interface I can create an extension method like follows:
public static void ChangeState(this IStateMachine StateMachine, IState NewState)
{
StateMachine.GetState().Exit();
StateMachine.SetState(NewState);
StateMachine.GetState().Enter();
}
What I really want is that there will be events that need to be fired, e.g.: a statechange-event.
However I don't want the StatechangeEvent to be a part of the IStateMachine interface, but it seems that that's the only way. I have several classes that implement IStateMachine, and therefore I have to redo the same code every time.
In C#, there are only extension methods. No extension properties or events.
You will have to declare the event on the interface.
To avoid the need to write the same event code over and over, you can create a base class.
Another possibility would be to "manually" implement the Publish-Subscribe pattern. That's what events in C# are.
You can add the extension methods Subscribe and Unsubscribe to IStateMachine.
They would use a possibly static class StateMachineSubscribers which also exposes the Subscribe and Unsubscribe methods. Additionally, it exposes a Raise method used by your ChangeState extension method.
The event with its corresponding delegate can be a part of a concrete class that implements that IStateMachine interface. So if you call SetState, on interface, its concrete implementaion of some concrete class is called, which inside of it raises an event you want.

Is it possible to register one event to another without helper method in C#?

I have two same events in different classes:
A.eventA
B.eventB
These two events: eventA and eventB are defined via the same delegate therefore the events have the same return value and parameters. Is it possible to fire A.eventA in the moment when B.eventB is fired?
I can write a method:
void return-value-of-delegate connect(parameters of delegate)
{
if (A.eventA != null)
{
A.eventA(parameters of delegate);
}
}
I was just wondering if I can shorten my code.
Thanks!
(Note: My code is a WPF project therefore WPF tag.)
EDIT: In class A is reference to the class B.
Whenever EventB fires, EventA also fires:
class A {
private B b;
public event EventHandler EventA {
add {
b.EventB += value;
}
remove {
b.EventB -= value;
}
}
public A() {
b = new B();
}
// ...
}
All the event listeners are registered in class B now.
You can not raise an event outside of the class. Only the class itself can raise it's own events. You can on the other hand, expose a public method accepting same parameters which internally raises the specified event.
Using Reflection is also not an option which only allows you to subscribe to and remove a subscription from an event of another class.
No, you can't, unless the code is in the class that declares the event. Events can only be fired from the declaring class. You probably have to consume an event with the arguments from both classes and in return fire the event, but you can't guarentee they will be fired at the same time, only about the same time, depending on the methods registered to each event, as they will be executed in the same thread.
The fact that the events are defined in different classes means that they are not the same event, even though they may have the same signature. You can't fire events from two separate classes at once.
Amongst other things, consider that an event is typically fired from an instance of a class. Which instance of B.eventB would you fire when A.eventA occurs?

Events with and without delegates in ASP.NET

In some ASP.NET examples i see that events are used with delegates like this and sometimes without them like this.
Please explain!
All events are delegate types (they all inherit from EventHandler that inherits from MulticastDelegate which interits from Delegate). Sometimes (or I would rather say most of the time) there is no need to declare your own custom delegate for an event though. You can use existing delegates as long as they match the signature of your event. With the introduction of EventHandler<T> in .NET Framework 2.0, the need for custom event delegates pretty much disappeared (as long as you follow the event design of the framework). So, doing the following:
// declare an event with a custom delegate type
public delegate void MyCustomEventHandler(object sender, EventArgs e);
public event MyCustomEventHandler SomeCustomEvent;
...is equivalent of this:
// declare an event with an existing delegate type
public event EventHandler SomeCustomEvent;
Should you have some custom EventArgs class, you can instead use the generic EventHandler<T> for your events:
class MyCustomEventArgs : EventArgs
{
// you custom stuff here
}
public event EventHandler<MyCustomEventArgs> SomeCustomEvent;
You don't need to specify a delegate if you're subscribing to an event created by someone else (your asp.net Page or some asp.net web control). Just provide a method that matches the delegate's signature.
The person who creates the event must provide the delegate. The subscriber just provides the method.
ASP.NET adds to the confusion as it will "wire up" events for you during compilation if you specify AutoEventWireup="true" within your page's definition.
Events in .NET are implemented with delegates.
From the page of your first link:
An event enables objects in a class to
notify other objects that something
has happened that they should perhaps
react to. Events in [.NET] are based
on a publisher-subscriber model. The
class that implements an event is
called the publisher of that event. A
subscriber class can subscribe to a
published event by registering an
appropriate event handler with the
published event.
...
The Delegate type determines the
signature of the event handlers that
can be registered with an event.
So the publishing class defines a delegate that the subscribing classes must implement. When the event is raised the subscribing class's methods are invoked through the delegate. And a method that handles an event is called an event handler. Events are properties of the class publishing the event. The keyword event is designed to maintain the publish/subscribe idiom.

ObservableCollection PropertyChanged event

I want to subclass ObservableCollection to add a property to it. Unfortunately, the PropertyChanged event is protected. Basically, I want to subclass it to have a SelectedItem that I can bind to for lists in my MVVM WPF app.
Here's the skeleton of my class:
public class SelectableList<T> : ObservableCollection<T>
{
public T SelectedItem {get;set;}
}
But I cannot do the following:
SelectableList<int> intList = new SelectableList<int>();
intList.PropertyChanged += new PropertyChangedEventHandler(intList_Changed);
because of access restrictions. This causes me to ask a deeper question. How is the UI notified of PropertyChanged events (e.g. Count property)? Note that I cannot do it in a code-behind.
My head is spinning, can someone please enlighten me?
SelectableList<int> intList = new SelectableList<int>();
((INotifyPropertyChanged)intList).PropertyChanged +=
new PropertyChangedEventHandler(intList_Changed);
ObservableCollection implements INotifyPropertyChanged explicitly, which means you have to cast the instance to the interface before you can access the interface's methods, properties and events. As to why this is done, I don't know. The Binding markup extension doesn't "know" ObservableCollections or any other type. It checks types to see if they implement or extend specific interfaces/base classes (INPC, INCC, DependencyObject, etc) and so doesn't care if the interface is implemented explicitly.
ObservableCollection (int .NET 3.5) appears to implement the PropertyChanged event in an interesting way.
protected event PropertyChangedEventHandler PropertyChanged;
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged;
This means that the protected PropertyChanged event is likely only meant to be used for internal implementation. The other INotifyPropertyChanged.PropertyChanged event is the one that actually fulfills the implementation of the INotifyPropertyChanged interface as an explicit interface. Strangely I do not see any place within the ObservableCollection where the INotifyPropertyChanged.PropertyChanged is actually raised. This may signal that this was a bug in .NET 3.5 although I haven't tested to confirm whether for example a property changed event is raised for Count when an item is added to a collection but that appears to be how it is supposed to work.
In the .NET 4.0 implementation it appears that the INotifyPropertyChanged.PropertyChanged event instead hooks to the same private delegate used by the protected PropertyChanged event which may have been a bug fix. It is also possible this is just due to differences in how auto event implementations are handled in .NET 4.0.
Correction: I have verified that the INotifyPropertyChanged.PropertyChanged event is raised by ObservableCollection so the assumptions I made above based on results from using Reflector to look at the ObservableCollection implementation must be inaccurate. My guess is that reflector is doing something strange bug I have no proof of that yet.
So to get your example to work you would need to write for this to work would look like the example below just as Will has demonstrated in his answer.
SelectableList<int> intList = new SelectableList<int>();
((INotifyPropertyChanged)intList).PropertyChanged +=
new PropertyChangedEventHandler(intList_Changed);
Interesting right? Using explicit interfaces is mainly used to avoid inevitable collisions in members required for a given interface but they can be used to in a sense hide the existence of a member.
If you would like to raise property change events for your own custom properties that you introduce in your subclass look into overriding and/or calling the protected OnPropertyChanged method that ObservableCollection also implements. This technique is a well adopted standard and allows subclasses to raise events or handle events without having access to the underlying event delegate. It is generally preferred to use this technique too by the way instead of having a subclass hook event handlers to it's own base classes events. For more examples look at how events in various controls are implemented in WinForms and WPF.
I tried to add a new property in
public class ResultCollection<T> : ObservableCollection<T>
{
Boolean _val;
public Boolean Val
{
get
{
return _val;
}
set
{
_val= value;
OnPropertyChanged(new PropertyChangedEventArgs("Val"));
}
}
}
I really didn't notice that PropertyChanged is defined as protected. Finally moved Val property to ViewModel.
The UI can and does get notified. This is a restriction JUST with ObservableCollection, which defines the PropertyChanged event as protected.
FWIW, I think you're better off leaving ObservableCollection alone and just adding another property to your VM.

Categories

Resources