说清委托和事件

一、委托什么

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

二、语法

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     }
复制代码

 

 

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

posted @ 2015-03-09 13:52  一生的爱恋  阅读(78)  评论(0)    收藏  举报