博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.NET高级:对委托与事件的深入理解
阅读量:5314 次
发布时间:2019-06-14

本文共 4491 字,大约阅读时间需要 14 分钟。

一、委托的理解

委托是一种类型(与枚举是一样的):特殊的地方是它指向一个方法

 

二、委托的使用场景:将一个方法抽象出来作为参数传递

class Program

{
static void Main(string[] args)
{
//MyDelegate md = (s) => { Console.WriteLine(s); Console.ReadKey(); };//lamda expression
//md += Fun1;
//md("Hello Delegate!");

string[] strArry = { "aa","bb","cc"};

ArryProcess(strArry, (s) => { return s + "*"; });//传入委托对数组中的值进行处理
Console.ReadKey();
}

static void ArryProcess(string[] strArry,StrProcessDele dele)

{
for (int i = 0; i < strArry.Length; i++)
{
strArry[i] = dele(strArry[i]);
}
}

static void Fun1(string s)

{
Console.WriteLine(s+"1111");
Console.ReadKey();
}
}

delegate void MyDelegate (string str);

delegate string StrProcessDele(string str);

 

三、委托的特性

一个委托对象可以指向多个方法=》委托的组合

按顺序执行注册它的方法,一般只用于事件中。

 

四、事件的本质理解

1.实现对一件事情发生的监听:(底层实现)

//声明一个委托类型

delegate void OnCount10(int i);

class Program

{
static void Main(string[] args)
{
Count count = new Count();
count._onCount10 = onCount10;
count.Next();
Console.ReadKey();
}

//在得到整数10的时候就会执行这个函数---》调用的人并不知道是怎么实现的,也不知道这个i是怎么传过来的

static void onCount10(int i)
{
Console.WriteLine("10的倍数:" + i);
}
}

class Count

{
public OnCount10 _onCount10;
private int i = 0;
public void Next()
{
while (true)
{
i++;
if (i % 10 == 0)
{
//到达10的整数的时候将这个数传出去,通知事件
_onCount10(i);//具体调用的函数,设计Count类的人并不知道---->解耦的思想
}
}
}
}

注:利用+=的方式注册多个委托响应函数

2.自定义三枪控件(委托方式实现)

自定义控件部分代码:

public partial class TribleClickButton : UserControl

{
public TribleClickButton()
{
InitializeComponent();
}

public delegate void TribleClickDelegate();

public TribleClickDelegate _ontribleClick;

private int count = 0;

private void button1_Click(object sender, EventArgs e)
{
count++;
if (count==3)
{
count = 0;
//执行委托(传递事件)
if (_ontribleClick != null)
{
_ontribleClick();
}
}
}
}

 

主窗体使用自定义控件部分代码:

public partial class Form1 : Form

{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)

{

//在窗体加载的时候给自定义控件注册响应事件

tribleClickButton1._ontribleClick = OnTribleClick;//给控件注册响应事件
}

private void OnTribleClick()

{
MessageBox.Show("自定义控件点击了三下");
}
}

以上是只是用委托使用自定义控件出现的问题;

1.让监听失效   2.冒充发送响应

private void button1_Click(object sender, EventArgs e)

{
tribleClickButton1._ontribleClick = null;//将其他的响应函数全部失效
}

private void button2_Click(object sender, EventArgs e)

{
tribleClickButton1._ontribleClick();//直接调用来冒充
}

对应解决方案:将委托对象设为Private,提供一个公共的方法对该委托实例添加或者移除响应函数

微软的解决方案:使用事件Event

自定义控件代码:

public partial class TribleClickButton : UserControl

{
public TribleClickButton()
{
InitializeComponent();
}

public delegate void TribleClickDelegate();

private TribleClickDelegate _ontribleClick;

public event TribleClickDelegate OnTribleClick//用一个中间的事件对象来提供对外只能使用+=或者-=来添加委托对象的响应实例

{
add { _ontribleClick += value; }//+=
remove{_ontribleClick-=value;}//-=
}

private int count = 0;

private void button1_Click(object sender, EventArgs e)
{
count++;
if (count==3)
{
count = 0;
//执行委托(传递事件)
if (_ontribleClick != null)
{
_ontribleClick();
}
}
}
}

主窗体代码:

public Form1()

{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)

{
tribleClickButton1.OnTribleClick += OnTribleClick1;//给控件注册响应事件
}

private void OnTribleClick1()

{
MessageBox.Show("自定义控件点击了三下");
}

微软更为简化的事件使用,不用自己定义一个委托的私有对象,在编译的时候会自动帮助生成这样的一个私有对象(使用反编译工具Reflector)

public partial class TribleClickButton : UserControl

{
public TribleClickButton()
{
InitializeComponent();
}

public delegate void TribleClickDelegate();

//private TribleClickDelegate _ontribleClick;

//时间的标准写法:public + event+委托类型+事件对象

public event TribleClickDelegate OnTribleClick;

//{
// add { _ontribleClick += value; }
// remove{_ontribleClick-=value;}
//}

private int count = 0;

private void button1_Click(object sender, EventArgs e)
{
count++;
if (count==3)
{
count = 0;
//执行委托(传递事件)
if (OnTribleClick != null)
{
OnTribleClick();
}
}
}
}

四、经过上面的探索,得出委托和事件的区别

1.委托与事件是没有科比性的

2.事件使用委托来实现的

3.委托是类,事件是一个对象,有Add和Remove方法来封装委托对象的响应函数

 

五、匿名函数和Lamda表达式

匿名函数的设计原理:有些函数只用调用一次就不再使用,不用专门的去使用一个函数名定义这个函数

Lamda表达式是对匿名函数的简化

实例:

public partial class Form1 : Form

{
public Form1()
{
InitializeComponent();
}

private MyDelegate myDelegate;

private void button1_Click(object sender, EventArgs e)

{
myDelegate("Hello!");
}

private void Form1_Load(object sender, EventArgs e)

{

//加载的时候注册委托对象的响应函数

myDelegate = delegate(string s) { MessageBox.Show(s); };//匿名函数的方式
myDelegate += (s) => { MessageBox.Show(s+" Again!"); };//Lamda表达式的方式(“{}”可以省略)

//如果{}中只有一句话是可以省略的。如果有返回值就可以省略return,将=》之后的表达式作为返回值

myDelegate1 = (s) => s=s + "*";

}

}

public delegate void MyDelegate(string s);

转载于:https://www.cnblogs.com/francis-ray/p/10156861.html

你可能感兴趣的文章
SRM 628 DIV2
查看>>
2018-2019-2 20165314『网络对抗技术』Exp5:MSF基础应用
查看>>
Python-S9-Day127-Scrapy爬虫框架2
查看>>
SecureCRT的使用方法和技巧(详细使用教程)
查看>>
自建数据源(RSO2)、及数据源增强
查看>>
关于View控件中的Context选择
查看>>
2018icpc徐州OnlineA Hard to prepare
查看>>
Spark的启动进程详解
查看>>
使用命令创建数据库和表
查看>>
机器视觉:SSD Single Shot MultiBox Detector
查看>>
在16aspx.com上下了一个简单商品房销售系统源码,怎么修改它的默认登录名和密码...
查看>>
linux下Rtree的安装
查看>>
多米诺骨牌
查看>>
Linq 学习(1) Group & Join--网摘
查看>>
asp.net 调用前台JS调用后台,后台掉前台JS
查看>>
苹果手表:大方向和谷歌一样,硬件分道扬镳
查看>>
Android面试收集录15 Android Bitmap压缩策略
查看>>
PHP魔术方法之__call与__callStatic方法
查看>>
ubuntu 安装后的配置
查看>>
【模板】对拍程序
查看>>