First of all, event is actually a kind of Delegate. to distinguish between them, we call the general delegate "plain delegate ".
WriteCodeIn the process, we often choose between delegate and event. I didn't think carefully about the reason for the choice before. Today, I finally had to spend half a day thinking about it ...... Okay, let's talk about the Code directly:
Using System;
Namespace Eventanddelegate
{
Public Delegate Void Testdelegate ( String S );
Public Interface Itest {
// [Difference] 1. The event can be used in the interface, but the plain delegate cannot (because it is a field)
Event Testdelegate teste; // Passed
Testdelegate testd; // Error: interfaces cannot contain fields
}
Public Class Parent {
Public Event Testdelegate teste;
Public Testdelegate testd;
Protected Void Raiseteste ( String S)
{
Teste (s );//The event 'eventanddelegate. Parent. teste' can only
//Be used from within the type 'eventanddelegate. parent'
}
}
Public Class Child: parent {
Void Childfunc ()
{
// [Difference] 2. The event cannot be called outside the class that declares it (even the subclass) (In addition, it can only be used for + = or-=), while the plain delegate allows
Testd ( " OK " ); // Passed
Teste ( " Failure " ); // Error: The Event 'eventanddelegate. Parent. teste' can only appear on
// The left hand side of + = or-= (Response t when used from
// The Type 'eventanddelegate. parent ')
// [Supplement] to trigger the event declared by the parent class in the subclass, the usual practice is to declare a protected raisexxx method in the parent class for the subclass to call.
Raiseteste ( " OK " ); // The class 'eventanddelegate. Kids' can only call
// 'Eventanddelegate. parentraiseteste' method to raise the event
// 'Eventanddelegate. Parent. teste'
// [Difference] Same as 2 #
Object O1 = Testd. target;
Object O2 = Teste. target; // The class 'eventanddelegate. Kids' can only call
// 'Eventanddelegate. parentraiseteste' method to raise the event
// 'Eventanddelegate. Parent. teste'
// [Difference] Same as 2 #
Testd. dynamicinvoke ( " OK " );
Teste. dynamicinvoke ( " OK " ); // The class 'eventanddelegate. Kids' can only call
// 'Eventanddelegate. parentraiseteste' method to raise the event
// 'Eventanddelegate. Parent. teste'
}
}
Class Other
{
Static Void Main ( String [] ARGs)
{
Parent P = New Parent ();
P. testd + = New Testdelegate (p_test1 ); // Passed
P. teste + = New Testdelegate (p_test1 ); // Passed
// [Difference] 3. The value assignment operator is not allowed for the event, whereas the plain delegate operator is allowed.
// Note: For plain delegate, using the value assignment operator means a replacement operation is performed!
P. testd = New Testdelegate (p_test2 ); // Passed
P. teste = New Testdelegate (p_test2 ); // Error: The Event 'eventanddelegate. Parent. teste' can only appear on
// The left hand side of + = or-= (Response t when used from
// The Type 'eventanddelegate. parent ')
// [Difference] Same as 2 #
P. testd ( " OK " ); // Passed
P. teste ( " Failure " ); // Error: The Event 'eventanddelegate. Parent. teste' can only appear on
// The left hand side of + = or-= (Response t when used from
// The Type 'eventanddelegate. parent ')
}
Static Void P_test1 ( String S)
{
Console. writeline ("P_test1:" +S );
}
Static Void P_test2 ( String S)
{
Console. writeline ("P_test2:" +S );
}
}
}
Analysis:
- The relationship between plain delegate and event is similar to that between field and property (in fact, the former is field, or we can regard event as a special property)
- It is precisely because 1 #, in terms of use, plain delegate has almost no restrictions, while event has strict restrictions (can only be used on the left of + = and-=)
Conclusion:
- event is more object-oriented.
- use plain delegate directly when needed; otherwise, use event when strict control is required.
- since the event cannot use the value assignment operator, it is more convenient to use plain delegate when only one response method is required for an event at any time.
- ...... (You can add)