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