C # Basic Knowledge Series-11 Delegates and Events

0. Introduction

Events and delegation are advanced features in C # and an interesting part of C #. Where an event occurs, there must be a commission; and a commission does not necessarily have an event. Why is there such a relationship? This requires starting from the definitions of events and delegations, and understanding the inner ones.

1. Commission

Speaking of delegation, I have to recall the anonymous method introduced in the Linq article, which mentioned the two types of Func and Action. These two types are delegates.

Delegation is defined in C # as an object-oriented form of method addressing scheme. Simply put, it is to define a type, and then indicate that this type represents a certain method. The delegate object is the method parameterization. Delegating can be used to pass a method as a parameter to another method, or it can be considered a special case of MethodInfo in reflection (in fact, it doesn't matter much).

Delegates don't care what the method is called or where the method comes from (which class or object it belongs to), only what parameters the method needs and what type it returns.

Speaking of which, let's take a look at how to define a delegation. The definition form of delegation is as follows:

delegate <返回类型>  委托名(参数列表);//参数列表代表任意个参数

From the previous definition form, we can know that the delegate is also a type, so its definition also conforms to the type definition specification. Now we define a delegate with no return value and no parameter type as the first delegate we create:

public delegate void FirstDel();// 类型名称是 FirstDel

Simple to use:

FirstDel del ;
del();// 会直接报错

If the above code is run, it will directly report an error, because you have not told the compiler what the variable del should be, that is, no value is assigned to del, and the delegate can be assigned to null, so when using it, you must pay attention to not null It is also impossible to run.

If the anonymous method is applied here, del can be assigned according to the following code:

del = ()=>
{
 	//省略方法   
}

Then we warm up and start to formally create a meaningful commission:

public delegate decimal CalculateArea(decimal height, decimal weight);

The above commission declares a specification for calculating the area, using the length and width for the area calculation, then let us assign a value to it:

CalculateArea squrare = (height, weight) => height * height;// 正方形
CalculateArea rectangle = (height, weight) => height * weight;// 矩形
CalculateArea triangle = (height, weight) => height * weight / 2; //三角形

We have created three methods for calculating the area in turn, namely square, rectangle, and triangle, and calling them will get the corresponding calculation results:

var squrareArea = squrare(10, 10);// 100
var rectangleArea = rectangle(19, 10);//190
var triangleArea = triangle(10, 5);//25

In particular, C # delegates support multicast, so it can also be used +, -registered and deleted. Multicast means that there are multiple listeners or response methods in the event and delegate. When the event is triggered or the delegate is called, the registered method group will be called. When assigning a delegate in this way, the delegate will be automatically converted to a method group. The simple understanding is that a list is created inside the delegate object, and then the methods assigned to it are stored.

So it will produce the following operations:

CalculateArea calculate = squrare;// calculate必须先赋值一个方法
calculate += rectangle;// 增加 矩形的面积计算方法
calculate += triangle; // 增加三角形的面积计算方法
calculate -= triangle; // 减去三角形的面积计算方法

There will be a question here, calculatewhat is the result of the operation, will it return an array or other types? Obviously not, because the return type defined by calculate is a decimal, so no other value will be returned.

Well, this raises another question. Which method's calculation result is returned, and other methods' calculation results? Here I tell you a result, only the execution result of the last registered method will be returned. Other methods are executed, but the execution result of the method cannot be received with variables.

So here is a very important practice. If there is a need to use the delegate as a method list, it is best to declare voidor discard the specific content of the return value.

2. Events

Event. In C #, an event is like a mechanism. When the program runs to a certain stage or encounters certain conditions, an event is triggered. Then if other code subscribes to this event, the subscribed code will be executed automatically. The description is very abstract. To put it simply, declare a delegate in the class, and mark the delegate as an event, and execute the event in another method. Among them, the class that triggers this event is called the publisher, and the class that accepts or registers the processing method is called the subscriber.

How to create or declare an event? There are two ways to declare an event, one is to use EventHandlerit directly , and the other is to first define a delegate and then use this delegate to define the event.

1. Use EventHandler

public class EventDemo
{
    public event EventHandler HandlerEvent;
}

2. Use a custom delegate

public class EventDemo
{
    public delegate void EventDelegate(object sender, EventArgs e);
    public event EventDelegate DelegateEvent;
}

The general event definition convention is commonly known as a void method. The first parameter is the sender to indicate the publisher of the event, which is the object type by default, and the second parameter is the event variable of the EventArgs type. Generally used to pass some parameters.

EventHandler has a generic version, and its declaration is as follows:

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);

The second parameter does not restrict TEventArgs, so we can use any type as an event variable.

Let's take a look again, there is nothing in EventArgs, nothing, only a default constructor and a few methods inherited from Object. So in development, we will define an event variable type ourselves, in order to maintain consistency will inherit EventArgs.

C # suggests that the definition of an event starts with On, indicating when to trigger, and the sample code does not comply with this specification.

3. Use events and delegates

Create a class with events:

public class EventDemo
{
    public delegate void EventDelegate(object sender, EventArgs e);

    public event EventDelegate DelegateEvent;


    public void Trigger()
    {
        if (DelegateEvent != null)// 触发事件,按需判断事件的订阅者列表是否为空
        {
            DelegateEvent(this, new EventArgs());
        }
    }
}

Use it:

EventDemo demo = new EventDemo(); 
demo.DelegateEvent += (sender, eventArgs) =>
{
    //省略订阅者的方法内容
}
demo.Trigger();//触发事件          

When the publisher tries to trigger the event, the subscriber will receive the message, and then the subscriber registration method will be called. The publisher passes a pair of sender and eventArgs to the subscriber, and the subscriber processes according to their own logic.

It can be clearly seen here that the event handler registration method is used +=, so there is also a corresponding one to -=cancel the subscription.

At this point, the basic concepts of delegation and events have been introduced, of course, that sentence, more content in practice. The C # event mechanism gives programmers more freedom to customize events, rather than being limited to certain frameworks. So you can try more C # events, maybe you can find more content that I do n’t know.

For more content please follow my blog

file

Guess you like

Origin www.cnblogs.com/c7jie/p/12740794.html