浅谈我对委托与事件的理解

  本人第一次写技术性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好累,先到这里吧,


  

你可能感兴趣的:(事件)