Frequent interview questions: C# delegates (delegate, Action, Func, predicate) and events
When I first started working, I felt that commissions and events were a bit mysterious, but after you understood them, it seemed that it was not as difficult as imagined. This blog post can be regarded as my review and summary of commissions and events.
Two, entrust
The delegate in C# is equivalent to the pointer function in C++, but the delegate is object-oriented, safe, and is a special class. Of course, it is also a reference type, and the delegate passes a reference to the method.
2.1、delegate
To declare a delegate, you must use the keyword "delegate". The delegate is declared first and then instantiated. At least 0 parameters, at most 32 parameters
The format is as follows:
private delegate string GetAsString();
A delegate is a class, so its instantiation is the same as that of a class, except that it always accepts a constructor that takes the delegate method as a parameter. There are two ways to call a delegate method, as follows:
int i = 10;
var method = new GetAsString(i.ToString);
//调用方法一
Console.WriteLine($"method方法{
method()}");
//调用方法二
Console.WriteLine($"method.Invoke方法{
method.Invoke()}");
operation result:
2.2、Action
Action is a generic delegate with no return value and can accept 0 to 16 incoming parameters
Action represents a delegate with no parameters and no return value
Action<int, string> indicates a delegate with incoming parameters int and string without return value
Action was used in [Implementation of Log4Net Logging] earlier. like:
public static void Debug(string message, Action RegistedProperties)
{
RegistedProperties();
log.Debug(message);
}
The calling method is:
PFTLog.Debug("测试扩展字段", () => {
LogicalThreadContext.Properties["LogType"] = "扩展字段内容";
});
During operation, just run the content in the Action directly.
2.3、Func
Func is a generic delegate with a return value that can accept 0 to 16 incoming parameters
Func means a delegate with no parameters and return value of int
Func<object, string, int> indicates that the incoming parameter is object, and the return value of string is a delegate of int
public static decimal GetTotal(Func<int, int, decimal> func, int a, int b)
{
return func(a, b);
}
calling method
var total = GetTotal((a, b) => {
return (decimal)a + b; }, 1, 2);
Console.WriteLine($"结果为{
total}");
operation result
2.4、predicate
predicate is a generic delegate that returns bool and can only accept one incoming parameter
predicate means that the incoming parameter is an int and returns a bool delegate
Define a method:
public static bool FindPoints(int a)
{
return a >= 60;
}
Define the Predicate delegate
Predicate<int> predicate = FindPoints;
transfer
var points = new int[] {
10,
50,
60,
80,
100 };
var result = Array.FindAll(points, predicate);
Console.WriteLine($"结果为{
string.Join(";", result)}");
operation result
2.5. Multicast delegation
The previous one only contains the invocation of one method, and the delegate can contain multiple methods. This kind of delegate is called a multicast delegate. Multicast delegates use two operators "+=" and "-+" to add and delete delegates.
First define two methods
public static void MultiplyByTwo(double v)
{
double result = v * 2;
Console.WriteLine($"传值:{
v};MultiplyByTwo结果为{
result}");
}
public static void Square(double v)
{
double result = v * v;
Console.WriteLine($"传值:{
v};Square结果为{
result}");
}
then call
Action<double> operations = MultiplyByTwo;
operations(1);
operations += Square;
operations(2);
operation result:
3. Events
Events are based on delegates, which provide a publish/subscribe mechanism for delegates, and event keywords need to be used to declare events.
Publisher: The publisher of an event, also known as the sender, is actually an object. This object will maintain its own state information by itself. When its own state information changes, it will trigger an event and notify some event subscribers;
Subscriber: Objects interested in events, also known as Receivers, can register interested events, and after the event publisher triggers an event, this code will be automatically executed
Do you feel familiar when you see sender? ! ! Don't be in a hurry, let's look at the declaration and use of the event
There is such an application scenario, if there is an abnormality in the system, the administrator needs to be notified in time. Then we need to add the function of notifying the administrator to our log records, but the question is, how to notify the administrator? At least not now. So we need to use events.
Add the code as follows, if you don’t know the log function, you can refer to [Log4Net log record implementation]
//声明一个通知的委托
public delegate void NoticeEventHander(string message);
//在委托的机制下我们建立以个通知事件
public static event NoticeEventHander OnNotice;
calling method
public static void Debug(string message, Action RegistedProperties)
{
RegistedProperties();
log.Debug(message);
//执行通知
OnNotice?.Invoke($"系统异常,请及时处理,异常信息:{
message}");
}
In the code that references the scene, first define a method to notify the administrator (here we directly Console.WriteLine out)
public static void Notice(string message)
{
Console.WriteLine($"通知内容为{
message}");
}
Register first, then trigger exception message
//注册方式一
PFTLog.OnNotice += Notice;
//注册方式二
//PFTLog.OnNotice += new PFTLog.NoticeEventHander(Notice);
PFTLog.Debug("测试扩展字段", () => {
LogicalThreadContext.Properties["LogType"] = "扩展字段内容";
});
operation result
Here I just need to define the publisher, and you can subscribe in any way, isn't it very, very simple.
After understanding the above events, let's talk about the object sender and EventArgs e that often appear in .Net
Coding specification of .Net Framework:
1. The name of the delegate type should end with EventHandler
2. The prototype definition of the delegate: it has a void return value and accepts two input parameters: an Object type and an EventArgs type (or inherited from EventArgs)
3. The name of the event is the remaining part after the delegation removes the EventHandler
4. Types inherited from EventArgs should end with EventArgs
Now let's take a custom event for a new book release as an example
Create the corresponding class file:
The eventer publishes the code:
public class BookInfoEventArgs : EventArgs
{
public BookInfoEventArgs(string bookName)
{
BookName = bookName;
}
public string BookName {
get; set; }
}
public class BookDealer
{
//泛型委托,定义了两个参数,一个是object sender,第二个是泛型 TEventArgs 的e
//简化了如下的定义
//public delegate void NewBookInfoEventHandler(object sender, BookInfoEventArgs e);
//public event NewBookInfoEventHandler NewBookInfo;
public event EventHandler<BookInfoEventArgs> NewBookInfo;
public void NewBook(string bookName)
{
RaiseNewBookInfo(bookName);
}
public void RaiseNewBookInfo(string bookName)
{
NewBookInfo?.Invoke(this, new BookInfoEventArgs(bookName));
}
}
event subscriber
public class Consumer
{
public Consumer(string name)
{
Name = name;
}
public string Name {
get; set; }
public void NewBookHere(object sender, BookInfoEventArgs e)
{
Console.WriteLine($"用户:{
Name},收到书名为:{
e.BookName}");
}
}
Event subscription and unsubscription
var dealer = new BookDealer();
var consumer1 = new Consumer("用户A");
dealer.NewBookInfo += consumer1.NewBookHere;
dealer.NewBook("book112");
var consumer2 = new Consumer("用户B");
dealer.NewBookInfo += consumer2.NewBookHere;
dealer.NewBook("book_abc");
dealer.NewBookInfo -= consumer1.NewBookHere;
dealer.NewBook("book_all");
operation result
After this example, we can know that the Object sender parameter represents the event publisher itself, and EventArgs e
is also the monitoring object. After in-depth understanding, do you feel that it is not as difficult as imagined.
Four. Summary
Here we talked about delegates and events. Using delegates and events in .Net development can reduce dependencies and layer coupling, and develop components with higher reusability.
Copyright statement: This article is collected or provided by netizens. If there is any infringement, please tell the moderator or leave a message, and this official account will be deleted immediately.
source:
https://www.cnblogs.com/snailblog/archive/2019/09/14/11520438.html
This article is published by mdnice multi-platform