说清委托和事件
一、委托什么
一个能存放符合某种格式的方法(方法签名)的指针的容器
二、语法
Demo1
//声明委托类(必须指定返回值类型和方法参数列表)
public delegate void DGSayHi(string str);
public partial class demo1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//创建委托对象,并为委托对象添加一个方法指针(方法对象地址),注意:不能存放签名和委托签名不一致的方法
DGSayHi dgSayHi = new DGSayHi(SayHiSomeWhere);
//调用委托(委托对象内部的方法就会被调用)
dgSayHi("哈哈哈");
}
public void SayHiChina()
{
Response.Write("你好");
}
public void SayHiSomeWhere(string location)
{
Response.Write(location + "你好");
}
1 //声明委托类(必须指定返回值类型和方法参数列表)
2 public delegate void DGSayHi(string str);
3 public partial class demo1 : System.Web.UI.Page
4 {
5 protected void Page_Load(object sender, EventArgs e)
6 {
7 //创建委托对象,并为委托对象添加一个方法指针(方法对象地址),注意:不能存放签名和委托签名不一致的方法
8 DGSayHi dgSayHi = new DGSayHi(SayHiSomeWhere);
9 //调用委托(委托对象内部的方法就会被调用)
10 dgSayHi("哈哈哈");
11 }
12 public void SayHiChina()
13 {
14 Response.Write("你好");
15 }
16 public void SayHiSomeWhere(string location)
17 {
18 Response.Write(location + "你好");
19 }
自定义按钮:Demo2
MyButton类:
public delegate void DGMyClick(DateTime clickTime);
public class MyButton : System.Web.UI.WebControls.Button
{
public DGMyClick dgMyClick;
public MyButton()
{
//为父类的单击事件注册一个方法
base.Click += MyButton_Click;
}
void MyButton_Click(object sender, EventArgs e)
{
if (dgMyClick != null)
{
dgMyClick(DateTime.Now);//调用委托
}
}
1 public delegate void DGMyClick(DateTime clickTime);
2 public class MyButton : System.Web.UI.WebControls.Button
3 {
4
5 public DGMyClick dgMyClick;
6 public MyButton()
7 {
8 //为父类的单击事件注册一个方法
9 base.Click += MyButton_Click;
10 }
11 void MyButton_Click(object sender, EventArgs e)
12 {
13 if (dgMyClick != null)
14 {
15 dgMyClick(DateTime.Now);//调用委托
16 }
17 }
demo2调用:
protected void Page_Load(object sender, EventArgs e)
{
MyButton m = new MyButton();
m.Text = "自定义按钮";
form1.Controls.Add(m);
m.dgMyClick = MyButtonClick;
}
public void MyButtonClick(DateTime clickTime)
{
Response.Write(string.Format("<script>alert('当前时间是{0}')</script>", clickTime.ToString()));
}
1 protected void Page_Load(object sender, EventArgs e)
2 {
3 MyButton m = new MyButton();
4 m.Text = "自定义按钮";
5 form1.Controls.Add(m);
6 m.dgMyClick = MyButtonClick;
7 }
8 public void MyButtonClick(DateTime clickTime)
9 {
10 Response.Write(string.Format("<script>alert('当前时间是{0}')</script>", clickTime.ToString()));
11 }
三、语法糖
在c#中有很多简洁语法,实质是由编译器在编译时转成完整语法
Demo3
public partial class demo3 : System.Web.UI.Page
{
public delegate void DGTest();
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
DGTest dg=Test1;//编译后:new DGTest(this.Test1)
dg+=Test2;//编译后:(DGTest) Delegate.Combine(dg,new DGTest(this.Test2))
dg+=Test3;//编译后:(DGTest) Delegate.Combine(dg,new DGTest(this.Test3))
dg -= Test3;//编译后:(DGTest) Delegate.Remove(dg,new DGTest(this.Test3))
dg();//编译后:dg.Invoke()
}
void Test1()
{
Response.Write("test1");
}
void Test2()
{
Response.Write("test2");
}
void Test3()
{
Response.Write("test3");
}
}
1 public partial class demo3 : System.Web.UI.Page
2 {
3 public delegate void DGTest();
4 protected void Page_Load(object sender, EventArgs e)
5 {
6
7 }
8
9 protected void Button1_Click(object sender, EventArgs e)
10 {
11 DGTest dg=Test1;//编译后:new DGTest(this.Test1)
12 dg+=Test2;//编译后:(DGTest) Delegate.Combine(dg,new DGTest(this.Test2))
13 dg+=Test3;//编译后:(DGTest) Delegate.Combine(dg,new DGTest(this.Test3))
14 dg -= Test3;//编译后:(DGTest) Delegate.Remove(dg,new DGTest(this.Test3))
15 dg();//编译后:dg.Invoke()
16 }
17 void Test1()
18 {
19 Response.Write("test1");
20 }
21 void Test2()
22 {
23 Response.Write("test2");
24 }
25 void Test3()
26 {
27 Response.Write("test3");
28 }
29 }
四、委托类
1、 委托编译后,声称一个同名的类,如DGTest,它继承于MulticastDelegate,MulticastDelegate继承于Delegate
2、 为委托追加方法的本质,是为被追加的方法创建一个新的委托对象,并将方法指针存入对象的父类的父类(Delegate)的IntPrt(专门存指针的一种数据类型)变量中,然后再将新创建的委托添加到当前委托对象(dg)的数组中。
五、委托的目的
1、 委托当返回值 demo4
public delegate void DGTest();
public partial class demo4 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Unnamed1_Click(object sender, EventArgs e)
{
DGTest dg = InvokeTest("1");
dg();
}
public DGTest InvokeTest(string s)
{
switch (s)
{
case "1":
return Test1;
case "2":
return Test2;
default:
return Test3;
}
}
void Test1()
{
Response.Write("test1");
}
void Test2()
{
Response.Write("test2");
}
void Test3()
{
Response.Write("test3");
}
}
1 public delegate void DGTest();
2 public partial class demo4 : System.Web.UI.Page
3 {
4 protected void Page_Load(object sender, EventArgs e)
5 {
6
7 }
8
9 protected void Unnamed1_Click(object sender, EventArgs e)
10 {
11 DGTest dg = InvokeTest("1");
12 dg();
13 }
14
15 public DGTest InvokeTest(string s)
16 {
17 switch (s)
18 {
19 case "1":
20 return Test1;
21 case "2":
22 return Test2;
23 default:
24 return Test3;
25 }
26 }
27 void Test1()
28 {
29 Response.Write("test1");
30 }
31 void Test2()
32 {
33 Response.Write("test2");
34 }
35 void Test3()
36 {
37 Response.Write("test3");
38 }
39 }
2、 方法当参数 demo5
public delegate void DGTest1();
public partial class demo5 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
InvokeTest(Test1);
}
public void InvokeTest(DGTest1 dgTest)
{
dgTest();
}
void Test1()
{
Response.Write("test1");
}
void Test2()
{
Response.Write("test2");
}
void Test3()
{
Response.Write("test3");
}
}
1 public delegate void DGTest1();
2 public partial class demo5 : System.Web.UI.Page
3 {
4 protected void Page_Load(object sender, EventArgs e)
5 {
6
7 }
8
9 protected void Button1_Click(object sender, EventArgs e)
10 {
11 InvokeTest(Test1);
12 }
13 public void InvokeTest(DGTest1 dgTest)
14 {
15 dgTest();
16 }
17 void Test1()
18 {
19 Response.Write("test1");
20 }
21 void Test2()
22 {
23 Response.Write("test2");
24 }
25 void Test3()
26 {
27 Response.Write("test3");
28 }
29 }
六、委托加工字符串
Demo6
public delegate string DGMakeUpStr(string str);
public partial class demo6 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
public string MakeUpStr(string str)
{
return str += "我";
}
public string[] MakeUpStrArr(string[] arrStr, DGMakeUpStr dg)
{
string[] arrstrNew = new string[arrStr.Length];
for (int i = 0; i < arrStr.Length; i++)
{
arrstrNew[i] = dg(arrstrNew[i]);
}
return arrstrNew;
}
protected void Button1_Click(object sender, EventArgs e)
{
string[] strArr = new string[] { "bb", "小李", "校长" };
string[] strArrNew = MakeUpStrArr(strArr, MakeUpStr);
for (int i = 0; i < strArrNew.Length; i++)
{
Console.WriteLine(strArrNew[i]);
}
}
1 public delegate string DGMakeUpStr(string str);
2 public partial class demo6 : System.Web.UI.Page
3 {
4 protected void Page_Load(object sender, EventArgs e)
5 {
6
7 }
8
9 public string MakeUpStr(string str)
10 {
11 return str += "我";
12 }
13 public string[] MakeUpStrArr(string[] arrStr, DGMakeUpStr dg)
14 {
15 string[] arrstrNew = new string[arrStr.Length];
16 for (int i = 0; i < arrStr.Length; i++)
17 {
18 arrstrNew[i] = dg(arrstrNew[i]);
19 }
20 return arrstrNew;
21 }
22 protected void Button1_Click(object sender, EventArgs e)
23 {
24 string[] strArr = new string[] { "bb", "小李", "校长" };
25 string[] strArrNew = MakeUpStrArr(strArr, MakeUpStr);
26 for (int i = 0; i < strArrNew.Length; i++)
27 {
28 Console.WriteLine(strArrNew[i]);
29 }
30 }
七、委托的缺点
可以用Click=null来清除所有注册的事件。
可以用Click来“假冒”事件触发。
解决方法:把委托成员设置成private,然后增加AddClickEventHandler、RemoveClickEventHander两个public的方法。
Demo7
protected void Page_Load(object sender, EventArgs e)
{
MyButton m = new MyButton();
m.Text = "自定义按钮";
form1.Controls.Add(m);
m.dgMyClick += MyButtonClick;
//m.dgMyClick = null;//可以轻易清空
}
public void MyButtonClick(DateTime clickTime)
{
Response.Write(string.Format("<script>alert('当前时间是{0}')</script>", clickTime.ToString()));
}
1 protected void Page_Load(object sender, EventArgs e)
2 {
3 MyButton m = new MyButton();
4 m.Text = "自定义按钮";
5 form1.Controls.Add(m);
6 m.dgMyClick += MyButtonClick;
7 //m.dgMyClick = null;//可以轻易清空
8 }
9 public void MyButtonClick(DateTime clickTime)
10 {
11 Response.Write(string.Format("<script>alert('当前时间是{0}')</script>", clickTime.ToString()));
12 }
优化方式:
MyButtonSelf类:
public delegate void DGMyClickSelf(DateTime clickTime);
public class MyButtonSelf : System.Web.UI.WebControls.Button
{
//私有化委托变量,使得外部无法直接操作修改此对象
private DGMyClickSelf dgMyClick;
//提供注册方法的方式,来为委托对象注册
public void AddClickMethod(DGMyClickSelf dg)
{
dgMyClick += dg;
}
public void RemoveClickMethod(DGMyClickSelf dg)
{
dgMyClick -= dg;
}
public MyButtonSelf()
{
base.Click += MyButtonSelf_Click;
}
void MyButtonSelf_Click(object sender, EventArgs e)
{
if (dgMyClick != null)
{
dgMyClick(DateTime.Now);//调用委托
}
}
}
1 public delegate void DGMyClickSelf(DateTime clickTime);
2 public class MyButtonSelf : System.Web.UI.WebControls.Button
3 {
4 //私有化委托变量,使得外部无法直接操作修改此对象
5 private DGMyClickSelf dgMyClick;
6 //提供注册方法的方式,来为委托对象注册
7 public void AddClickMethod(DGMyClickSelf dg)
8 {
9 dgMyClick += dg;
10 }
11 public void RemoveClickMethod(DGMyClickSelf dg)
12 {
13 dgMyClick -= dg;
14 }
15 public MyButtonSelf()
16 {
17 base.Click += MyButtonSelf_Click;
18 }
19 void MyButtonSelf_Click(object sender, EventArgs e)
20 {
21 if (dgMyClick != null)
22 {
23 dgMyClick(DateTime.Now);//调用委托
24 }
25 }
26 }
八、事件
事件机制会自动将修饰的委托变量改成私有,并同时提供一个add和remove方法
即委托的优化版
Demo8
MyButtonEvent类:
public class MyButtonEvent : System.Web.UI.WebControls.Button
{
public event DGMyClick dgMyClick;
public MyButtonEvent()
{
base.Click += MyButtonSelf_Click;
}
void MyButtonSelf_Click(object sender, EventArgs e)
{
if (dgMyClick != null)
{
dgMyClick(DateTime.Now);//调用委托
}
}
}
1 public class MyButtonEvent : System.Web.UI.WebControls.Button
2 {
3 public event DGMyClick dgMyClick;
4 public MyButtonEvent()
5 {
6 base.Click += MyButtonSelf_Click;
7 }
8 void MyButtonSelf_Click(object sender, EventArgs e)
9 {
10 if (dgMyClick != null)
11 {
12 dgMyClick(DateTime.Now);//调用委托
13 }
14 }
15 }
调用类:
public partial class demo8 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
MyButtonEvent m = new MyButtonEvent();
m.Text = "自定义按钮";
form1.Controls.Add(m);
m.dgMyClick += MyButtonClick;//不能实例化,不能设置null,事件机制会自动将修饰的委托变量改成私有,并同时提供一个add和remove方法,只能用+=,-=
}
public void MyButtonClick(DateTime clickTime)
{
Response.Write(string.Format("<script>alert('当前时间是{0}')</script>", clickTime.ToString()));
}
}
1 public partial class demo8 : System.Web.UI.Page
2 {
3 protected void Page_Load(object sender, EventArgs e)
4 {
5 MyButtonEvent m = new MyButtonEvent();
6 m.Text = "自定义按钮";
7 form1.Controls.Add(m);
8 m.dgMyClick += MyButtonClick;//不能实例化,不能设置null,事件机制会自动将修饰的委托变量改成私有,并同时提供一个add和remove方法,只能用+=,-=
9 }
10 public void MyButtonClick(DateTime clickTime)
11 {
12 Response.Write(string.Format("<script>alert('当前时间是{0}')</script>", clickTime.ToString()));
13 }
14 }
------------------------------------------------------------------------------------------------------------------------------------------


浙公网安备 33010602011771号