C # events, delegation mechanism. This example is very good. The source code is provided, and we will understand it all at once. We also recommend that you read the story of Peter to learn about delegation events,

Source: Internet
Author: User

Events are a very important concept. Our programs trigger and receive various events at all times: mouse click events, keyboard events, and various operating system events. An event is a message sent from an object. For example, if a user presses a button and a file changes, data on the socket reaches. The object that triggers an event is called the sender. The object that captures the event and responds to the event is called the receiver. An event can have multiple recipients.

In the asynchronous mechanism, events are a very common method for communication between threads. For example, you can click a button on the interface to execute a time-consuming task. The program starts a thread to process this task. a progress bar is displayed on the user interface to indicate the execution status of the user task. This function can be used to process events. The class that processes the task can be used as the message sender. When the task starts, the "TaskStart" event is issued, and the "TaskDoing" event is issued at different times during the task, parameters are included to describe the proportion of tasks. When the task ends, a "TaskDone" event is sent to receive and process these events on the screen. In this way, the function is implemented, and the module coupling between the interface and the backend is also the lowest.

Specifically speaking, C # language, the implementation of events depends on the concept of "proxy" (delegate). First, let's take a look at proxy.

Proxy (delegate)

Delegate is a type in C #. It is actually a class that can hold a reference to a method. Unlike other classes, the delegate class can have a signature and can only hold references to methods that match its signature. Its functions are very similar to function pointers in C/C ++. It allows you to pass the method m of Class A to the object of Class B, so that the object of Class B can call this method m. But compared with function pointers, delegate has many advantages that function pointers do not possess. First, the function pointer can only point to static functions, while delegate can reference both static functions and non-static member functions. When referencing a non-static member function, delegate not only saves the reference to this function entry pointer, but also saves the reference to the class instance that calls this function. Second, compared with function pointers, delegate is an object-oriented, secure, and reliable managed object. That is to say, the runtime can ensure that the delegate points to a valid method. You do not need to worry that the delegate will point to an invalid or out-of-bounds address.

It is easy to implement a delegate. You can use the following three steps to implement a delegate:

1. Declare a delegate object. It should have the same parameter and return value type as the method you want to pass.

2. Create a delegate object and pass in the functions you want to pass as parameters.

3. Use the object created in the previous step to call the method where an asynchronous call is to be implemented.

The following is a simple example:

Public class MyDelegateTest

{

// Step 1: declare the delegate object

Public delegate void MyDelegate (string name );

// This is the method we want to pass. It has the same parameter and return value type as MyDelegate.

Public static void MyDelegateFunc (string name)

{

Console. WriteLine ("Hello, {0}", name );

}

Public static void Main ()

{

// Step 2: Create a delegate object

MyDelegate md = new MyDelegate (MyDelegateTest. MyDelegateFunc );

// Step 3: Call delegate

Md ("sam1111 ");

}

}

Output result: Hello, sam1111

Let's take a look at how the event is handled:

Event)

In C #, event processing is actually a delegate with a special signature, as shown below:

Public delegate void MyEventHandler (object sender, MyEventArgs e );

The two parameters, sender represents the event sender, and e is the event parameter class. The MyEventArgs class is used to contain event-related data. All event parameter classes must be derived from the System. EventArgs class. Of course, if your event does not contain special parameters, you can directly use the System. EventArgs class as the parameter.

With the implementation of delegate, We can summarize the implementation of custom events into the following steps:

1: defines the delegate object type. It has two parameters. The first parameter is the event sender object, and the second parameter is the event parameter class object.

2: Define the event parameter class. This class should be derived from the System. EventArgs class. This step can be omitted if the event does not contain parameters.

3: Define the event processing method. It should have the same parameter and return value type as the delegate object.

4: Use the event keyword to define the event object. It is also a delegate object.

5: Use the + = Operator to add events to the event queue (the-= operator can delete events from the queue ).

6: Call the delegate method to write the event trigger method where an event needs to be triggered. In general, this method should be a protected access restriction. It cannot be called in public mode, but can be inherited by the quilt class. The name can be OnEventName.

7: Call the event trigger method to trigger the event in an appropriate place.

The following is an example. The example imitates the container and control mode. An event is triggered by the control to capture and process the event in the container.

Event trigger:

/// <Summary>

/// Event trigger

/// </Summary>

Public class Control

{

Public delegate void SomeHandler (object sender, System. EventArgs e );

 

/**

* The System. EventHandler provided by the System can be used. To describe the situation, the custom delegate is used.

* If you need to use your own defined types in the event parameters, you must also define your own delegate

*/

// Public event System. EventHandler SomeEvent;

Public event SomeHandler SomeEvent;

Public Control ()

{

// The delegate used here must be consistent with the name of the event.

// This. SomeEvent + = new System. EventHandler (this. Control_SomeEvent );

This. SomeEvent + = new SomeHandler (this. ProcessSomeEvent );

}

 

Public void RaiseSomeEvent ()

{

EventArgs e = new EventArgs ();

Console. Write ("Please input 'A ':");

String s = Console. ReadLine ();

 

// Trigger the event when the user inputs a small a; otherwise, the event is not triggered.

If (s = "")

{

SomeEvent (this, e );

}

}

 

// The Event trigger processes the event by himself. The parameters of this method must be consistent with the sound name in the proxy.

Private void ProcessSomeEvent (object sender, EventArgs e)

{

Console. WriteLine ("hello ");

}

}

Event receiver:

/// <Summary>

/// Event receiver and handler

/// </Summary>

Class Container

{

Private Control ctrl = new Control ();

Public Container ()

{

// The delegate used here must be consistent with the name of the event.

// Ctrl. SomeEvent + = new EventHandler (this. OnSomeEvent );

Ctrl. SomeEvent + = new Control. SomeHandler (this. ResponseSomeEvent );

Ctrl. RaiseSomeEvent ();

}

 

Public static void Main ()

{

Container pane = new Container ();

// This readline is used to suspend the program, otherwise the screen will flash and see nothing

Console. ReadLine ();

}

 

// This is the response of the event recipient to the event

Private void ResponseSomeEvent (object sender, EventArgs e)

{

Console. WriteLine ("Some event occur! ");

}

}

The running result is as follows:

Please input 'A':

Hello

Some event occur!

 

Event Application

For example, a subwindow is displayed on the main screen of the program. At this time, the main screen can still receive user operations (subwindows are non-modal ). Perform operations in the subwindow. Different data is displayed on the Main Screen Based on the operation results. I found some programmers implement this function as follows:

After a sub-window is displayed on the main screen, the pointer is handed over to the sub-screen. Then, the sub-screen uses this pointer to call the method provided by the main screen to change the data display on the main screen. This can achieve the goal, but there is a strong coupling between modules. Generally, calls between modules should be in the single direction: module A calls Module B, and Module B should not reverse call A; otherwise, it will damage the program level and enhance the coupling degree, it also makes it difficult to change and append functions.

At this time, the correct method should be to issue various events during the Sub-window operation, and the main window will capture these events for processing, and each module will focus on doing its own thing, you do not need to ask about other modules.

 

 

 

Using System;
Using System. Collections. Generic;
Using System. Linq;
Using System. Text;

Namespace ConsoleApplication1
{
Class Program
{

Public Program ()
{
// The delegate used here must be consistent with the name of the event.
// Ctrl. SomeEvent + = new EventHandler (this. OnSomeEvent );
Ctrl. SomeEvent + = new Control. SomeHandler (this. ResponseSomeEvent );
Ctrl. RaiseSomeEvent ();

}
Private Control ctrl = new Control ();
Static void Main (string [] args)
{
Program pr = new Program ();
Console. ReadLine ();
}
// This is the response of the event recipient to the event
Private void ResponseSomeEvent (object sender, EventArgs e)
{
Console. WriteLine ("Some event occur! ");
}

}

/// <Summary>
/// Event trigger
/// </Summary>
Public class Control
{
Public delegate void SomeHandler (object sender, System. EventArgs e );

/**
* The System. EventHandler provided by the System can be used. To describe the situation, the custom delegate is used.
* If you need to use your own defined types in the event parameters, you must also define your own delegate
*/
// Public event System. EventHandler SomeEvent;
Public event SomeHandler SomeEvent;
Public Control ()
{
// The delegate used here must be consistent with the name of the event.
// This. SomeEvent + = new System. EventHandler (this. Control_SomeEvent );
This. SomeEvent + = new SomeHandler (this. ProcessSomeEvent );
}

Public void RaiseSomeEvent ()
{
EventArgs e = new EventArgs ();
Console. Write ("Please input 'A ':");
String s = Console. ReadLine ();

// Trigger the event when the user inputs a small a; otherwise, the event is not triggered.
If (s = "")
{
SomeEvent (this, e );
}
}

// The Event trigger processes the event by himself. The parameters of this method must be consistent with the sound name in the proxy.
Private void ProcessSomeEvent (object sender, EventArgs e)
{
Console. WriteLine ("hello ");
}
}

}

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.