
It is impossible, just to grasp and penetrate into this deep meaning, studying Events (events) in the spaces of the basic and, at first glance, infinite C #.
When I studied Events (not within the framework of .NET!), I spent a lot of effort to finally figure out how they work and should be constructed. Therefore, I decided to publish my own methodology for understanding the structure of a
user event , which is the
event keyword in C #.
I will not quote the already tortured
MSDN , but I will try to explain clearly and accessiblely.
What you need to learn:
- 1. You should not be afraid of learning. Please read slowly and thoughtfully.
- 2. You must understand the classes and methods.
- 3. You need
to know what delegates are. Although, you can try to understand them in the course of reading the article.
An event is nothing more than a situation in which it occurs, an action or several actions will occur. Speaking in terms of software modeling, an
Event is a named delegate, when invoked, all the methods of a given signature that are signed at the time of the event call will be launched. This interpretation, although it reveals the whole essence of the structure of the event, but not only confuses the beginners of “Sharp progers”, but does not make it possible to rationally present the whole meaning in the programmer's head.
')
So, an
Event is a situation, in the event of which, some actions will occur. The event itself has a specific structure.
Suppose there is such a task: three classes are defined. The first class will count to 100 using a loop. The other two classes will wait for the counter in the first class to calculate, for example, up to 71, and after that everyone will output the phrase “It's time to act, after all, 71!” To the console. Simply put, when detecting the value 71, they will be called by the method, respectively, for each class. Putting everything on the shelves.
1. Simulation of the situation.
Prepare these three simplest classes, leaving the entry point to the
main program untouched.
ClassCounter class and its
Count () method in which the count will be produced. (In the code I omit the namespace
namespace , for it is as clear as day).
class ClassCounter
Two other classes (named after
Handler_I and
Handler_II ), which should respond to an event occurring using public void
Message () methods. Each according to the method, as agreed.
class Handler_I
class Handler_II { public void Message() { Console.WriteLine(", 71!"); } }
Let me remind you that when the counter counts up to 100 and reaches 71, the Message () methods for the Handler_I and Handler_II classes should work.
Now let's go back to the ClassCounter class and create a counter using the
for loop with the counter variable
int i .
class ClassCounter
The first stage is completed. We have a class counter and two classes that will display messages. Conditions of the problem: as soon as
i = 71 , the
Message () methods for the two classes
Handler_I and
Handler_II should work.
2. Registration of the event.
We abstract from programming. The event we want to create will represent the phrase "... the counter counts. And as soon as it is equal to 71, actions must be executed." So, we need the condition "as soon as it is equal to 71". We represent it using the
conditional operator if .
class ClassCounter
Construct an event
event . We determine by the methods that should work when i = 71 their
signature (or prototype).
The signature of the method is the so-called specification (or simple words "pattern") of a. method or methods. It is a combination of the type name that the method returns, plus the name of the types of the input parameters (in order! Order is very important.)
For example, the
int method
NewMethod (int x, char y) will have the signature
int (int, char) , and the
void method
NewMethod () will void (void) .
As interpreted by MSDN , events (event) are based on
delegates (delegate), and the delegate, in
very simple language, is “a variable storing a reference to a method”. As you already understood, because our event will refer to two methods void Message (), we must determine the signature of these methods, and make a delegate based on this signature. The signature looks like this:
void (void) .
Define a delegate (let's call it MethodContainer):
class ClassCounter
Next, we create an event using the event keyword and associate it with this delegate (
MethodContainer ), and, therefore, with methods that have a
void (void) signature. The event must be public, because it must be used by different classes that need to be reacted in some way (classes Handler_I and Handler_II).
The event has the syntax: public event <Name of the Delegate> <Name of the Event>;
The delegate name is the name of the delegate to which our methods “refer”.
class ClassCounter
Now let's run our onCount event, in the condition when i = 71:
if (i == 71) { onCount(); }
Everything.
Event created . The methods that this event triggers are determined by signatures and a delegate is created based on them. The event, in turn, is created based on the delegate. It's time to show the
onCount event, which methods should work (after all, we indicated only their signature).
3. Subscription.
Let's return to the entry point of the program main and create an instance of the class
ClassCounter . And also create instances of classes that should start. (They must be
public ).
class Program { static void Main(string[] args) { ClassCounter Counter = new ClassCounter(); Handler_I Handler1 = new Handler_I(); Handler_II Handler2 = new Handler_II(); } }
Now we specify the
onCount event, the methods that should be launched.
This happens as follows:
<ClassOrObject>. <EventName> + = <ClassHeyMethod Must Started>. <MethodAppropriateSignature> .
No brackets after the method! We do not call him, but simply indicate his name.
class Program { static void Main(string[] args) { ClassCounter Counter = new ClassCounter(); Handler_I Handler1 = new Handler_I(); Handler_II Handler2 = new Handler_II();
Check.
Now it remains to run the
ClassCounter class
counter and wait for i to be equal to 71. As soon as i = 71, the
onCount event is
triggered by the
MethodContainer delegate, which (in turn) starts the
Message () methods that have been
subscribed to the event.
class Program { static void Main(string[] args) { ClassCounter Counter = new ClassCounter(); Handler_I Handler1 = new Handler_I(); Handler_II Handler2 = new Handler_II(); Counter.onCount += Handler1.Message; Counter.onCount += Handler2.Message;
Result:
It's time to act, because already 71!
Similarly, already 71!
Conclusion
Try to understand the meaning and order of the event.
- 1. Determine the condition of occurrence of the event and the methods that should work.
- 2. Determine the signature of these methods and create a delegate based on this signature.
- 3. Create a public event based on this delegate and call when the condition triggers.
- 4. Be sure to (anywhere) subscribe to this event using the methods that should trigger and the signatures of which match the delegate.
The class in which you create an event (generate) is called a publisher class, and the classes whose methods subscribe to this event with the help of
"+ =" are subscriber classes.
Remember! If you have not subscribed to the event and its delegate is empty, an error will occur.
To avoid this, it is necessary to subscribe, or not to trigger an event at all, as shown in the example (since the event is a delegate, its absence is a “null reference”
null ).
if (i == 71) { if (onCount != null) { onCount(); } }
You can always unsubscribe using the "
- = " operator: <ClassOrObject>. <EventName> - = <ClassCeyMethod Must Started>. <MethodAppropriateSignature>.
The advantage of Events is obvious:
the publisher class that generates the event does not need to know how many
subscriber classes subscribe or unsubscribe. He created an event for certain methods, limiting them to a delegate for a particular signature.
Events are widely used to create your own control components (buttons, panels, etc.).
The smallest ones may have a question: what to do if the methods that should work have an incoming parameter (or even more than one!)?
Answer: It's all about the delegate on whom the event is based. Or rather, the signature of methods suitable for the delegate. When you construct a delegate that “accepts” a method with a parameter, then (!) The event will trigger this parameter when it starts. Naturally, the parameter can be anything.
A few words about .NET-events. Microsoft has simplified the task of constructing delegates: .NET offers a ready-made
EventHandler delegate, and so on. The "batch" of
EventArgs input parameters. Want an event? You take the finished EventHandler, define it in the parameters, “push” them into the
class , and inherit the class from the EventArgs. And then - as scheduled)
Many developers claim (and I agree with them) that the main problem of “misunderstanding” of events is their specific field of application, and as a result, there are few examples available. Well, do not forget about the practice.
PS If you have never used delegates, better try to practice on delegates, and then try to understand this article.
I hope I brought a little insight into this difficult topic. Successes!