Hello.
In this lecture, we're going to talk about Question 43, what our events and event is a message sent
by an object to signal the occurrence of an action.
Events are the dots, nuts, implementation of the observer design pattern.
Let's implement the same logic we had in the lecture about the observatory's own pattern.
We want the Bitcoin price reader object to notify other objects about the reading of the bitcoin price.
This time will do so using events.
We'll start by defining a delegate that will represent the function or functions that will be executed
once the price reading event has been raised.
The Bitcoin price reader will own an event of these delegates type.
Let's take a moment to stop and think about what happened here.
We declared an event belonging to the bitcoin price rigging across an event is always over delegates.
I remember a delegate is a type whose instances hold a reference to admit it or methods with particular
parameters released and return type would never start in this field would be a method or methods.
Taking this email as a parameter and returning nothing as we declared it staggered as void.
So what is the difference between an event and a regular field of a delegate type?
In other words, what would be the difference between those two?
Both seem like fields of a delegated type, but this isn't the event.
Let's try to attach some method to both of them.
So far, an event in the field of delegates type act exactly the same, but here is the difference.
As you can see, I can't invoke the event from outside of the class.
It belongs to I can invoke the non event delegate without a problem.
This is a critical difference.
Only the class that owns an event can raise it.
Events are used to send notifications about some action.
So imagine what would happen if any grass could raise them and the code could raise the price red event
with the price it wants, triggering invite notifications all around the system.
The event delegate must be public so the subscribers can subscribe to it, but it must only be invaluable
from within the class that owns it.
And that's what the event keyword enforces.
All right.
Let's move on with the implementation.
We defined an event in the bitcoin price reader class when the bitcoin price is red.
We want to raise that event.
So simply invoke all methods stored in the event dugout.
This means all subscribers will be notified that the event occured.
As you can see, I executed the event delegate by the Invoke method.
Let me show you why I did it.
This is a standard way of invoking a delegate.
But price, what event will be known before and this subscriber subscribes to it in this case, here
I will get another reference exception.
I wanted to use the new air conditioner operator, which will only execute this delegate if it's not
new.
But if I try to use it like this, it won't compile.
It's not possible to use this operator like this.
That's why, instead of simply calling this delegate, I used the Invoke method.
The result will be the same, so the delegate will be invoked, but I am able to use the normal conditional
operator to make sure no exception will be thrown.
All right.
Let's summarize what happened in this class.
We declared an event which is of a delegate type when the bitcoin price is red.
We want to raise the event so all subscribers are notified.
Let's move on to the subscribers.
Each subscriber must contain a method that is compatible with the event delegate.
In our case, avoid method accepting this email.
Luckily, we currently have such method in the notifier class.
Now we can subscribe, then notify classes to the Bitcoin price with our class so they are notified
when the event is raised.
And that's it.
All that's left to do is to call the current price method.
It seems like everything is working.
Let's see again what happened when the right current price method is executed.
This is what happens.
It reads the current price and it raises the price for that event.
The price great event is invoked and since the update method from IMO price tend to notifier and push
price trends, Notifier are attached to the event delegate.
They get executed.
So, for example, this is a method that is attached to this event handler.
All right.
Everything works as expected.
There is one improvement we can make, though instead of having our own price delegates for the event,
we can use the event handler or delegate that is predefined in C-sharp.
This is the signature of this delegate, as you can see, it carries the information about the object
that raised that event and event arguments, even arcs is a base class for other event arguments we
want.
In our case, the argument of an event is the bitcoin price that has been.
Let's create our own type derived from event arcs.
To make sure this type of event argument will be used, we must use the generic event handler.
We must now turn to the cold that raises that event to mark the event handler of price event asks delegates
type.
As you can see us, the first argument we pass this.
So the center of the event, the second argument is that price read event arcs object holding the price.
The last thing left to do is to change the update method in the price point and the different classes.
All right.
Let's make sure everything works.
Looking exactly as before.
You may think that this is more complicated than the cold that we had before, and this is true.
Nevertheless, I wanted to show you this event handler type as it is used in many Microsoft's frameworks
based on events, for example in Windows Forums or Windows Presentation Foundation, desktop applications
or user actions like clicking on a button or closing a window trigger events and those events are defined
well.
The event handler delegate.
In those use cases, the sender argument is used by the subscribers, which we did not need to do in
our code.
One last thing before we wrap up, this is generally a good practice to unsubscribe from the event handler
before the object getting notified about the event is discarded.
I don't want to get into details about why it is important, as this lecture is quite long already.
So let me just give you a very quick overview.
When a subscriber subscribes to be notified about a state turned in, some object actually then reference
is created between them.
It is needed because the event handler holds a reference to a method stored in the object that will
be notified about the event.
So our reference to this object is necessary.
It may happen that we think an object is no longer in use while the garbage collector still sees a reference
to it and will not remove it from memory.
For example, consider a desktop application with some a main window and a third window that opens when
you click some button.
The child window is subscribed to an event of the main window, so the reference from the main window
to third window exists when we close the child window.
It should be removed from memory, but the garbage collector will see this reference and will decide
this object should not be removed as the applications user keeps opening and closing child windows.
More and more memory is being used, but none of it is being freed.
This situation is called a memory leak.
Over time, it may slow the application down or even cause it to crash due to out of memory exception
unsubscribing from events when it's possible.
For example, when the third window is being closed, it's a way of preventing that.
Let's summarize events are the ultimate way of implementing the observer design pattern.
They are used to send a notification from an object to all objects subscribed.
The pattern of using events is as follows The class that we will be sending.
Notifications owns an event which is another great object that wants to be notified about an event can
attach their own methods to this delegate.
When the Observer Bluegrass raises the event, it does so by invoking the methods stored in the delegate.
This way, all methods from the observers are being executed during the interview.
You can be asked What is the difference between an event and the field of the delegate type?
A public field of a delegate type can be invoked from anywhere in the cold.
Events can only be invoked from the class they belong to.
Why is it a good practice to unsubscribe from events when a subscribed object is no longer needed?
Because as long as it is subscribed, a hidden reference between the observer and the observer exists,
and it will prevent the garbage collector from removing the observer object from memory.
All right.
This has been a long lecture, but I believe we covered the pretty complex topic of events.
Thanks for following along, and I see you in the next lecture.