一、委托的理解
委托是一种类型(与枚举是一样的):特殊的地方是它指向一个方法
二、委托的使用场景:将一个方法抽象出来作为参数传递
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);