.NET DELEGATES: A C # BedTime Story Chinese version (Part 1)
Author: Chris Sells
Translator: glory
[Translation] C # advanced article. Chris Sells is one of the author of "ATL INTERNALS". All program debugging environments in the translation are Microsoft Visual Studio.NET 7.0 Beta2 and Microsoft .NET Framework SDK Beta2. The code is the article, please read the code carefully J]
Type coupling
Once, a foreign country in the south has a hardworking worker named Peter. He is a hundred Boss, but his BOSS is a small person, he insists that Peter continues to report work. Since Peter does not want to be stared at home by BOSS, he promises to BOSS to report a progressive progress. Peter uses the type reference regular callback BOSS to achieve this commitment:
Using system; // [Translation: Translator Supplement]
Class worker
{
Public Void Advise (BOSS BOSS)
{
_boss = boss;
}
Public void doork ()
{
Console.writeline ("Worker: Work Started");
IF (_boss! = null) _boss.workstarted ();
Console.writeline ("Worker: Work Progressing");
IF (_boss! = null) _boss.WorkProgressing ();
Console.writeline ("Worker: Work Completed");
IF (_boss! = NULL)
{
INT grade = _boss.workcompleted ();
Console.writeline ("Worker grade =" grade);
}
}
PRIVATE BOSS _BOSS;
}
Class boss
{
Public void workstarted () {/ * boss is not concerned. * /}
Public void WorkProgressing () {/ * boss is not concerned. * /}
Public int Workcompleted ()
{
Console.WriteLine ("IT's About Time!");
Return 2; / * Out of 10 * /
}
}
Class universe
{
Static void main ()
{
Worker peter = new worker ();
Boss boss = new boss ();
Peter.advise (BOSS);
Peter.dowork ();
Console.writeline ("Main: worker completed work";
Console.readline ();
}
}
/ * [Translation: The following is the above program output results:
Worker: Work Started
Worker: Work Progressing
Worker: Work Completed
IT's About Time!
Worker grade = 2
Main: worker completed work
】 * /
interface
Now, Peter has become a special person, not only can endure despicable BOSS, and Universe has also established close contacts. Peter feels that universe is also interested in his work process. Unfortunately, in addition to ensuring that BOSS can be notified, if not add a special notification method and callback to universe, Peter cannot inform the Universe's working process. Peter hopes isolated inform potential to achieve those conventions from the notification method, for which he decided to peel methods to the interface: using System; // [Annotation: Translator supplement]
Interface iWorkeRevents // [Translation] This is the interface that is separated]
{
Void Workstarted ();
Void Workprogressing ();
Int workcompleted ();
}
Class worker
{
Public void advise (iWorkeRevents Events) // [Translation: The type of parameter "is the interface reference]
{
_events = events;
}
Public void doork ()
{
Console.writeline ("Worker: Work Started");
IF (_events! = null) _events.workstarted ();
Console.writeline ("Worker: Work Progressing");
IF (_events! = null) _events.WorkProgressing ();
Console.writeline ("Worker: Work Completed");
IF (_events! = NULL)
{
Int grade = _Events.Workcompleted ();
Console.writeline ("Worker grade =" grade);
}
}
Private iWorkeRevents_events;
}
Class boss: iWorkeRevents // [Translation: BOSS implementation this interface]
{
Public void workstarted () {/ * boss is not concerned. * /}
Public void WorkProgressing () {/ * boss is not concerned. * /}
Public int Workcompleted ()
{
Console.WriteLine ("IT's About Time!");
Return 3; / * Out of 10 * /
}
}
Class universe
{
Static void main ()
{
Worker peter = new worker ();
Boss boss = new boss ();
Peter.advise (boss); // 【Translation: or Peter.advise ((iWorkeRevents) boss;】
Peter.dowork ();
Console.writeline ("Main: worker completed work";
Console.readline ();
}
}
/ * [Translation: The following is the above program output results:
Worker: Work Started
Worker: Work Progressing
Worker: Work Completed
IT's About Time!
Worker grade = 3
Main: worker completed work
】 * /
Delegate
Unfortunately, since Peter is busy notifying BOSS to implement this interface, it does not take care of the universe, but he knows that soon, at least, he has abstract the reference to BOSS, so other implementations What people who have an IWORKEREVENTS interface can receive a working progress notice. [Translation: Please refer to the previous code example and the translation] However, Peter's BOSS is still extremely dissatisfied, "Peter!" BOSS roar, "Why do you want me to start working, when do you work? I don't care? These events, you not only force me to achieve these methods, you also wast your valuable working hours, etc. I returned from the incident. When I need to take a long time, you should wait for my time to be greatly extended! Don't you think about something else? Don't always come to me? "
At this time, Peter realized that although the interface is useful in many cases, the particle size of the interface is not fine enough when processing the event. He also can do just notify the listener's event that is really interested. Therefore, Peter decided to solve the method limbs in the interface into several independent entrust functions, each seems to be a small interface with only one way.
Using system; // [Translation: Translator Supplement]
Delegate void workstarted ();
Delegate void Workprogressing ();
Delegate int Workcompleted ();
Class worker
{
Public void doork ()
{
Console.writeline ("Worker: Work Started");
IF (Started! = null) Started ();
Console.writeline ("Worker: Work Progressing");
IF (Progressing! = NULL) progressing ();
Console.writeline ("Worker: Work Completed");
IF (Completed! = NULL)
{
INT grade = completed ();
Console.writeline ("Worker grade =" grade);
}
}
Public Workstarted Started; //:: Write a more rules: public workstarted started = null;]
Public WorkProgressing Progressing; //: PUBLIC WORKPROGRESSING Progressing = null;
Public workcompleted completed; // 【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【【】
}
Class boss
{
Public int Workcompleted ()
{
Console.writeline ("Better ...");
Return 4; / * Out of 10 * /
}
}
Class universe
{
Static void main ()
{
Worker peter = new worker ();
Boss boss = new boss ();
Peter.completed = New Workcompleted (Boss.WorkComplete);
Peter.dowork ();
Console.writeline ("Main: worker completed work"; console.readline ();
}
}
/ * [Translation: The following is the above program output results:
Worker: Work Started
Worker: Work Progressing
Worker: Work Completed
Better ...
Worker grade = 4
Main: worker completed work
】
* /
[Translation: "But when processing the event, the particle size of the interface is not fine enough" can be explained in the following example, please observe the procedure carefully, think about this unfavorable point J
Using system;
Interface iWorkStartedEvent
{
Void Workstarted ();
}
Interface iWorkProgressingevent
{
Void Workprogressing ();
}
Interface iWorkCompletedEventEvent
{
Int workcompleted ();
}
Class worker
{
Public void Advise (iWorkCompletedEvent aevent)
{
_event = aevent;
}
Public void doork ()
{
Console.writeline ("Worker: Work Completed");
IF (_event! = null)
{
INT grade = _Event.Workcompleted ();
Console.writeline ("Worker grade =" grade);
}
}
Private iWorkCompletedEvent_event;
}
Class Boss: iWorkCompletedEvent
{
Public int Workcompleted ()
{
Console.writeline ("Better ...");
Return 4; / * Out of 10 * /
}
}
Class universe
{
Static void main ()
{
Worker peter = new worker ();
Boss boss = new boss ();
Peter.advise (BOSS);
Peter.dowork ();
Console.writeline ("Main: worker completed work";
Console.readline ();
}
}
/ * The following is the result of the upper program output:
Worker: Work Completed
Better ...
Worker grade = 4
Main: worker completed work
* /
】
Static listener
This has reached an incident without BOSS to bother his goal. However, Peter is still unable to make Universe a listener. Because universe is a fully enclosed entity, it is not appropriate to hook the universe's instance (how much resources need to be needed for multiple instances of universe ...). Peter realized that the commissioned hooks should be hooked on the static member of Universe, because the commission is fully adapted to static members:
Using system;
Delegate void workstarted ();
Delegate void Workprogressing ();
Delegate int Workcompleted ();
Class worker
{
Public void doork ()
{
Console.writeline ("Worker: Work Started");
IF (Started! = null) Started ();
Console.writeline ("Worker: Work Progressing");
IF (Progressing! = NULL) progressing ();
Console.writeline ("Worker: Work Completed");
IF (Completed! = NULL)
{
INT grade = completed ();
Console.writeline ("Worker grade =" grade);
}
}
Public Workstarted Started = NULL;
Public WorkProgressing Progressing = NULL;
Public Workcompleted Completed = NULL;
}
Class boss
{
Public int Workcompleted ()
{
Console.writeline ("Better ...");
Return 4; / * Out of 10 * /
}
}
// 【Translation: The above code is an translator added】
Class universe
{
Static void workerStartedWork ()
{
Console.Writeline ("Universe Notices Worker Starting Work");
}
Static int workercompletedWork ()
{
Console.writeline ("Universe PleaseD with Worker's Work");
Return 7;
}
Static void main ()
{
Worker peter = new worker ();
Boss boss = new boss ();
Peter.completed = New Workcompleted (Boss.WorkCompleted); // [Translation]
Peter.Started = New Workstarted (universe.workerstartedWork);
Peter.comPleted = New Workcompleted (universe.workercompletedWork); // 【Translation: This line of code makes "×" The line of code is white.
Peter.dowork ();
Console.writeline ("Main: worker completed work";
Console.readline ();
}
}
/ * [Translation: The following is the above program output results:
Worker: Work Started
Universe Notices Worker Starting Work
Worker: Work Progressing
Worker: Work Completed
Universe pleased with worrs work
Worker grade = 7
Main: worker completed work
】 * /
event
Unfortunately, Universe has now become too busy and not to pay attention to a personal -Universe with its own entrusted replacement of Peter's BOSS, which is obviously set to an unexpected side effect of the Worker class. [Translation: Please refer to the previous example code and the translation], if the PETER's BOSS is impatient, he can trigger Peter's delegate (Peter's BOSS) // peter's BOSS yourself
IF (peter.completed! = null) peter.completed ();
Peter wants to make sure that these two situations will not occur. He realized that you must add registration and anti-registration functions for each delegate, so that listeners can add or remove them, but no one can empty the entire event list. Peter did not implement these methods, in contrast, he used Event keyword to let the C # compiler gave him this purpose:
Class worker
{
// ...
Public Event Workstarted Started;
Public Event WorkProgressing Progressing;
Public Event Workcompleted Completed;
}
Peter knows that the keyword Event makes the entrustment have such features: only C # clients are allowed to use = or - = operator to add or remove them, so they force BOSS and Universe to behave in elegance:
Static void main ()
{
Worker peter = new worker ();
Boss boss = new boss ();
Peter.comPleted = New Workcompleted (Boss.WorkComplete);
Peter.Started = New Workstarted (universe.workerstartedWork);
Peter.comPleted = New Workcompleted (Universe.WorkerCompletedWork);
Peter.dowork ();
Console.writeline ("Main: worker completed work";
Console.readline ();
}
[Translation: The following is the full code:
Using system;
Delegate void workstarted ();
Delegate void Workprogressing ();
Delegate int Workcompleted ();
Class worker
{
Public void doork ()
{
Console.writeline ("Worker: Work Started");
IF (Started! = null) Started ();
Console.writeline ("Worker: Work Progressing");
IF (Progressing! = NULL) progressing ();
Console.writeline ("Worker: Work Completed");
IF (Completed! = NULL)
{
INT grade = completed ();
Console.writeline ("Worker grade =" grade);
}
}
Public Event Workstarted Started;
Public Event WorkProgressing Progressing;
Public evenet workcompleted completed;
Class boss
{
Public int Workcompleted ()
{
Console.writeline ("Better ...");
Return 4; / * Out of 10 * /
}
}
Class universe
{
Static void workerStartedWork ()
{
Console.Writeline ("Universe Notices Worker Starting Work");
}
Static int workercompletedWork ()
{
Console.writeline ("Universe PleaseD with Worker's Work");
Return 7;
}
Static void main ()
{
Worker peter = new worker ();
Boss boss = new boss ();
Peter.completed = New Workcompleted (Boss.WorkCompleted); // [Translation: √]
Peter.Started = New Workstarted (universe.workerstartedWork);
Peter.comPleted = New Workcompleted (Universe.WorkerCompletedWork);
Peter.dowork ();
Console.writeline ("Main: worker completed work";
Console.readline ();
}
}
/ *
The following is the result of the upper program output:
Worker: Work Started
Universe Notices Worker Starting Work
Worker: Work Progressing
Worker: Work Completed
Better ... // [Translation: BOSS also notifies j "√" that line code is useful, but slowly, the 4 points of BOSS play did not get, and only 7 points given by universe.
Universe pleased with worrs work
Worker grade = 7
Main: worker completed work
* /
】