.NET高级:对委托与事件的深入理解

一、委托的理解

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

 

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

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);

posted @ 2018-12-22 11:58  Francis_Ray  阅读(711)  评论(0编辑  收藏  举报