Introduction
If you have read the delegate and event text in aspx.com/dotnet/csharp/csharp_20091008_768.html "target = _ self> C #, I think you have a basic understanding of the Delegate and event. However, there are still many issues that are far from the full content of delegation and events. This article will discuss some more detailed questions about delegation and events, including some common questions, as well as event accessors, exception handling, timeout processing, asynchronous method calls, and so on.
Why use events instead of delegate variables?
In the delegate and event in C #, we propose two reasons for using an event in the type to provide external method registration instead of directly using the delegate variable. It mainly focuses on encapsulation and ease of use, but it is missing a bit,The event should be triggered by the event publisher rather than the client (Client Program.What does this sentence mean? See the following example:
NOTE:Note the change in terms here. When we talk about events separately, we will talk about the publisher, subscriber, and client ). When we talk about the Observer mode, we talk about the topic and the observer ). The client is usually a Program class that contains the Main () method.
Class Program{
Static Void Main (String[] Args ){
PublishserPub =New Publishser();
SubscriberSub =New Subscriber();
Pub. NumberChanged + =NewNumberChangedEventHandler (sub. OnNumberChanged );
Pub. DoSomething ();// The event should be triggered through DoSomething ()
Pub. NumberChanged (100 );// But can be called directly in this way, improper use of delegate Variables
}
}
// Define the delegate
Public Delegate VoidNumberChangedEventHandler (IntCount );
// Define the event publisher
Public Class Publishser{
Private IntCount;
Public NumberChangedEventHandlerNumberChanged;// Declare the delegate variable
//Public Event NumberChangedEventHandlerNumberChanged; // declare an event
Public VoidDoSomething (){
// Complete some work here...
If(NumberChanged! =Null){// Trigger the event
Count ++;
NumberChanged (count );
}
}
}
// Define the event subscriber
Public Class Subscriber{
Public VoidOnNumberChanged (IntCount ){
Console. WriteLine ("Subscriber notified: count = {0 }", Count );
}
}
The code above defines a NumberChangedEventHandler delegate, and then we create the event Publisher and Subscriber. When the delegate variable is used, the client can directly trigger the event through the delegate variable, that is, directly call pub. NumberChanged (100), which affects all subscribers that have registered the delegate. WhileThe event is intended to be triggered by the event publisher in a specific action of the event, for example, when a condition is met in the DoSomething () method.By adding the event keyword to publish events, event publishers will be more encapsulated,The event is only subscribed to by other types, and the client cannot directly trigger the event (statement pub. numberChanged (100) cannot be compiled. An event can only be triggered within the Publisher class of the event Publisher (for example, in the pub method. in DoSomething (), that is, the NumberChanged (100) statement can only be called within Publisher.
You can try to comment out the line of code that declares the delegate variable, and then cancel the annotation of the following event declaration. At this time, the program cannot be compiled. When you use the event keyword, this action is directly triggered on the client, that is, calling pub. NumberChanged (100) directly is forbidden. An event can only be triggered by calling DoSomething. This is the intention of the event, and the encapsulation of the event publisher will be better.
It is like if we want to define a numeric type, we will use int instead of object. It is not necessarily a good thing to give too many capabilities to the object. The more appropriate the better. Although using delegate variables directly is usually not a problem, it gives the client the ability not to have, but the use of events can limit this ability, more accurately encapsulate the type.
NOTE:There is also a convention commonly known as the rule, that is, the name of the method for subscribing to events, usually "On event name", such as OnNumberChanged here.
Why is the return value defined by the delegate usually void?
Although not required, we find that many delegate definition return values are void. Why? This is because the delegate variable can be registered by multiple subscribers. If the return value is defined, the methods of multiple subscribers will return a value to the publisher, the result is that the method value returned later overwrites the previous return value. Therefore, you can only obtain the return value of the last method call. You can run the following code to test it. In addition, the publisher and subscriber are loosely coupled. The publisher does not care who subscribes to its events or why it subscribes, let alone the return value of the subscriber, therefore, returning the method return value of the subscriber is not necessary in most cases.
Class Program{
Static Void Main (String[] Args ){
PublishserPub =New Publishser();
Subscriber1Sub1 =New Subscriber1();
Subscriber2Sub2 =New Subscriber2();
Subscriber3Sub3 =New Subscriber3();
Pub. NumberChanged + =NewGeneralEventHandler (sub1.OnNumberChanged );
Pub. NumberChanged + =NewGeneralEventHandler (sub2.OnNumberChanged );
Pub. NumberChanged + =NewGeneralEventHandler (sub3.OnNumberChanged );
Pub. DoSomething ();