说清委托和事件

一、委托什么

一个能存放符合某种格式的方法(方法签名)的指针的容器

二、语法

Demo1

 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         }
View Code

自定义按钮:Demo2

MyButton类:

 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         }
View Code

demo2调用:

 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         }
View Code

三、语法糖

在c#中有很多简洁语法,实质是由编译器在编译时转成完整语法

Demo3

 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     }
View Code

四、委托类

1、  委托编译后,声称一个同名的类,如DGTest,它继承于MulticastDelegate,MulticastDelegate继承于Delegate

2、  为委托追加方法的本质,是为被追加的方法创建一个新的委托对象,并将方法指针存入对象的父类的父类(Delegate)的IntPrt(专门存指针的一种数据类型)变量中,然后再将新创建的委托添加到当前委托对象(dg)的数组中。

五、委托的目的

1、 委托当返回值 demo4

 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     }
View Code

2、 方法当参数 demo5

 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     }
View Code

六、委托加工字符串

Demo6

 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         }
View Code

七、委托的缺点

可以用Click=null来清除所有注册的事件。

可以用Click来“假冒”事件触发。

解决方法:把委托成员设置成private,然后增加AddClickEventHandler、RemoveClickEventHander两个public的方法。

Demo7

 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         }
View Code

优化方式:

MyButtonSelf类:

 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     }
View Code

八、事件

事件机制会自动将修饰的委托变量改成私有,并同时提供一个add和remove方法

即委托的优化版

Demo8

MyButtonEvent类:

 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     }
View Code

调用类:

 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     }
View Code

 

------------------------------------------------------------------------------------------------------------------------------------------

 软谋在线教育,最适合大学生、上班族的在线软件培训,主要教授asp.net动态网站制作,yy教育房间远程实时授课,每节课录制成高清视频课后分享,老师白天八小时全职在线辅导,不懂就问。加qq群:138800420 即可免费试听。

原文地址:https://www.cnblogs.com/ruanmou001/p/3626069.html