• 说清委托和事件


    一、委托什么

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

    二、语法

    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 即可免费试听。

  • 相关阅读:
    1021. 从前有座山——java
    1004. 西西弗斯式的命运——java
    1025. 水枪灭火——java
    1020. 分解质因数——java
    1024.排序——C语言
    1024. 排序——java
    1022. Fib数列——java
    1006. 求和游戏——java
    1005. 数独——java
    SpringBoot 升级到 2.1 后,启动程序时控制台不打印 API 的解决方法及一些感想
  • 原文地址:https://www.cnblogs.com/ruanmou001/p/3626069.html
Copyright © 2020-2023  润新知