C#委托与事件学习笔记
委托事件学习笔记
本文是学习委托和事件的笔记,水平有限,如有错漏之处,还望大神不吝赐教。
- 什么是委托?从字面意思来解释,就是把一个动作交给别人去执行。在实际开发中最常用的就是使一个方法可以当做一个参数传递,以便在方法中可以根据实际情况实现不同的功能。
- 什么是事件?事件就是发生的事情,例如点击了一下鼠标,对应鼠标单击事件,双击速表对应鼠标双击事件……进行winform开发的时候就能了解到很多的事件,可以说只有想不到的事件,没有微软不能提供的事件。实际上事件是一种特殊的委托,定义一个事件的时候也需要指定事件所依赖的委托。
如何声明一个委托呢?
声明委托需要使用关键字delegate其他与声明一个方法相同,需要指定委托使用的参数和返回值,但是委托的声明是没有具体实现的,委托的实现是在初始化的时候指定委托的方法。
//声明一个委托,返回值为空,需要两个参数
//委托的声明与方法类似,所以内部的方法也必须是与委托声明包含相同的传入参数和返回值
public delegate void customdelegate(object sender, customargs args);
实现自定义的参数类,winform开发里面可以经常看到eventargs这个类,他是与触发的事件相关的参数
//此对象继承自eventargs用于传递给委托的参数
//不是强制要求如此声明,只是根据默认约定,实际项目中可根据需要进行声明
public class customargs : eventargs
{
public string name { get; set; }
}
下面的类是委托和事件使用的公共类
//用于委托学习的公共类
public class customcommon
{
//声明一个事件
//事件是一种特殊的委托,除了不用指定一个初始的方法之外,使用方法与委托相似
//事件只能通过+=和-=的方式添加需要执行的方法
//委托只能在声明它的类内部触发
public event customdelegate customhandler;
public void showname(object sender, customargs args)
{
console.writeline($"your name is :{args.name}");
}
public void showother(object sender, customargs args)
{
console.writeline("此方法是showother");
}
//定义此方法用于触发事件
public void onhandler(object sender,customargs args)
{
if (customhandler != null)//判断事件是否为空
{
customhandler(sender, args);
}
}
委托的初始化即调用
//委托初始化的时候需要传入一个方法
//委托就是把方法交给别人去执行,所以一定需要在添加了方法之后委托才能执行.所以,必须在初始化的时候添加第一个方法
customcommon common = new customcommon();
customargs cargs = new customargs() { name = "此坑已满" };
customdelegate handler = new customdelegate(common.showname);//此处传入的是方法的声明,而不是方法执行的结果
//handler(null,cargs);//委托的调用与方法的调用相同
委托内部可以同时添加多个相同声明的方法,称为委托链
//委托链调用
//委托可以通过+=和-=添加和移除方法
//相同对象的同一个方法只能添加一次
//委托链的执行时按照添加方法的顺序进行执行,如果委托返回值不是void那么委托链的返回值就是最后一个方法执行后的返回值,其他方法的返回值全部都会被舍弃
handler += common.showother;
//调用此委托链
//委托链调用传入的参数,会传递给内部的所有方法,且每个方法获取到的参数一模一样
//handler(null, cargs);
事件的使用
//测试事件
//事件在winform程序中使用的非常多,例如按钮的click事件,winform的窗体类都是分部类
//查看designer类就可以看到click+=为事件添加一个处理方法
common.customhandler += showmethod;
//common.onhandler(null, null);
//匿名方法
//匿名方法,即不指定方法的名称,使用delegate关键字代替即可,使用匿名方法可以不用为实现委托而专门去定义一个方法,只需要实现方法即可
action<int> action = new action<int>(delegate (int value) { console.writeline($"this value is {value}"); });
//action(10);
//lambda表达式
//lambda更加简化了委托的编程只需要=>即可实现方法
//lambda使用格式,(x,y)=>{dosomthing}
//如果只有一个参数那么可以写为 x=>{dosomthidng}
//如果只有一句代码,那么可以写为x=>dosomthing
//如果没有参数,那么就不能省略()必须写为()=>{dosomthing}
//x,y是参数的表示符,c#编译器会自动推测其类型,而其值即为调用委托时传入的值
//如下t的类型为int其值为10
action<int> actionl = (t) => { console.writeline($"this is a method for test lambda value is {t}"); };
actionl(10);
console.readkey();
//下面是事件使用的方法
public static void showmethod(object sender, customargs args)
{
console.writeline("this is a method for test event");
}
将方法当做一个参数传递
/// <summary>
/// 测试委托作为参数传递的方法
/// </summary>
/// <param name="list"></param>
/// <param name="func"></param>
public int paradeletest(list<int> list, func<list<int>, int> func)
{
if (list != null && list.count > 0)//判断数组必须包含值,仅为了测试代码简单而实现,实际项目请根据需要进行设置
{
return func(list);//对数据进行操作
}
else
{
return -1;
}
}
list<int> list = new list<int>{ 1, 4, 23, 124, 54 };
//将委托作为参数传入,可以实现在不同的需求情况下,实现不同的功能
int ave = common.paradeletest(list, (x) => { return (int)x.average(); });//计算list的平均值
int max = common.paradeletest(list, x => x.max());//计算list中的最大值
console.writeline($"this list average is {ave},max is {max}");
推荐阅读
-
OpenCV学习笔记(18)双目测距与三维重建的OpenCV实现问题集锦(三)立体匹配与视差计算
-
HTML5与CSS3基础教程第八版学习笔记16-21章 - 平凡世界平凡人
-
C#基础_学习笔记--结构体
-
Python数据分析与挖掘实战学习笔记
-
python学习笔记之列表(list)与元组(tuple)详解
-
数据结构与算法学习笔记:栈
-
《深入理解java虚拟机》学习笔记--第三章:垃圾收集器与内存分配策略 jvm
-
《深入理解java虚拟机》学习笔记--第四章:虚拟机性能监控与故障处理工具 虚拟机java
-
《深入理解java虚拟机》学习笔记--第四章:虚拟机性能监控与故障处理工具 虚拟机java
-
《深入理解java虚拟机》学习笔记--第三章:垃圾收集器与内存分配策略 jvm