本人第一次写技术性BLOG,特意跑到里屋来,恳请各位批评指正!
最近学习了C#,感觉委托与事件对于第一次接触的人来说有点特别,所以仅发此文做笔记。
委托可以看做一种类,因为本身委托并不是类,相当于C++里面的函数指针,我的理解是,可以看做是一种对“函数方法名"的一种引用与替换。它只是表明了在创建的时候它是一种比较奇怪的名字,MS总是以EventHandler作为其方法名的结尾,然后在运行的过程中,再”编译“出相应的类。(这里我没有看过C#编译器生成的代码,所以姑且称为编译吧)
我本身是自学过一些PHP,可以看出PHP里面本身并不存在委托这种形式,因为只要是变量名后尾接上()就可以把字符串,当做方法来运行,这算是弱类型带来的一点好处吧。
看看来自MSDN的代码
public delegate int PerformCalculation(int x, int y);
可以看出来它并不是类,但是委托又可以实例化
new PerformCalculation(x,y);
所以说,委托可以看做一种函数方法名的抽象。把一些具有相同参数类型与个数的方法,联系到了一起,只要是符合以上两点,那么就可以通过委托的方式来调用不同的方法。
委托既可以在类外,也可以在类的内部来声明,代码如下:
using System;
using System.Collections.Generic;
using System.Text;
namespace Delegate
{
//类外的委托
public delegate void PasswordUpdatedEventHandler(string x,string y);
class User
{
private string userName;
private string userPassword;
public User(string name, string password)
{
this.userName = name;
this.userPassword = password;
}
public void UpdatePassword(string oldPassword, string newPassword)
{
if (oldPassword == this.userPassword)
{
this.userPassword = newPassword;
Console.WriteLine("修改密码成功");
}
}
//当然一般是不允许修改用户名的,这里只是为了说明问题
public void UpdateName(string oldName, string newName)
{
if (oldName == this.userName)
{
this.userName = newName;
Console.WriteLine("修改用户名成功");
}
}
}
class Program
{
static void Main(string[] args)
{
User user = new User("green", "123");
//实例化委托
//因为委托在User的外面,且UpdatePassword不是静态方法,
//所以需要通过user.UpdatePassword才可以调用到UpdatePassword方法
//当然如果委托放在了User类的内部,可以相当于内部类
PasswordUpdatedEventHandler pwd = new PasswordUpdatedEventHandler(user.UpdatePassword);
pwd("123", "111");
}
}
}
可以看到提示说修改密码成功。新密码变为了”111“,pwd这个委托实例化出来的东东,就可以看做作为user.UpdatePassword的一种名称上的替换,当然这里只是为了方便理解才这么说的。
委托可以组成一种链状的东东,可以把几个可以通过委托来调用的方法连起来,这样只一起,就可以执行一连串的动作了。例如上文中的class Tester类中要变成这样
class Program
{
static void Main(string[] args)
{
User user = new User("green", "123");
//实例化委托
PasswordUpdatedEventHandler pwd;
pwd = user.UpdateName;
pwd += user.UpdatePassword;
pwd("123", "999");
}
}
可能例子没有什么实际的意义,这里只是为了说明。。。
运行后结果会提示密码修改成功,注意看这里
PasswordUpdatedEventHandler pwd;
pwd = user.UpdateName;
pwd += user.UpdatePassword;
声明了一个PasswordUpdateEventHandler类型的pwd,然后赋予了user.UpdateName之后又+=了一个user.UpdatePassword。我把委托看做是一种链式的方式存储的,第二行的pwd=user.UpdateName算是声明了头结点,然后连接了下一个结点。这样只需赋值一遍pwd(”123“,”999“),就连着执行了两个函数UpdateName和UpdatePassword。
讲委托,是为了给事件做铺垫,一般都是放在一起,用了事件,就会去执行委托来的方法。直接看代码:
using System;
using System.Collections.Generic;
using System.Text;
namespace DelegateHandlerEvent
{
//委托
public delegate void ChangedPasswordEventHandler(object sender,EventArgs e);
//用户类
class User
{
private string name;
private string password;
//事件
public event ChangedPasswordEventHandler ChangedPassword;
//构造函数,输入用户名,密码
public User(string name, string password)
{
this.name = name;
this.password = password;
}
//修改密码
public void ChangePassword(string oldPassword, string newPassword)
{
if (oldPassword == this.password)
{
this.password = newPassword;
if (ChangedPassword != null)
{
ChangedPassword(this,null);
}
}
else
{
throw new WrongPwdException("原密码错误!");
}
}
}
//自定义异常
class WrongPwdException : Exception
{
public WrongPwdException(string msg) : base(msg)
{
}
}
class Program
{
public static void Main()
{
User user = new User("green", "123");
//注册事件
user.ChangedPassword += new ChangedPasswordEventHandler(user_ChangedPassword);
try
{
user.ChangePassword("123", "456");
}
catch(WrongPwdException wpe)
{
Console.WriteLine("不允许修改密码:"+wpe.Message);
}
}
static void user_ChangedPassword(object sender, EventArgs e)
{
Console.WriteLine("成功修改密码!");
}
}
}
大概的意思都在代码注释里,可以看看。
代码写的很垃圾,没模仿出.net Framework的感觉来,凑合看看吧。
事件就是扩充其他类的代码,在其他类执行到某部分的时候,其他类会看有没有事件注册。如果没有则不执行,如果有事件注册了,那么就跳转到相应的部分去执行,这样,原本的类就可以再添加新的处理方法,来扩充原有类,执行更多的功能了。
额第一次写BLOG好累,先到这里吧,