C#中的委托与事件

来源:互联网 发布:宾汉姆顿大学 知乎 编辑:程序博客网 时间:2024/05/03 03:53

委托

我们习惯把数据或者对象作为参数传递给方法,比如:

int i = int.Parse("99");

如果我们把方法作为参数传递给方法,这就需要用到委托了。我们从字面上理解委托,就像是A委托B去办一件事情一样,其实在C#中也有这一层的含义。


首先我们先看C#中的语法:

public delegate void DoSomethingEventHandler();

delegate是关键字,EventHandler算是一个声明委托类型的一个命名标准。委托的定义就这么简单。

让我们先来看一段代码:

    class Student {        public static void MakeTea() {            Console.WriteLine("Got it!");        }    }    class Teacher    {        //声明一个委托        public delegate void DoSomething();        static void Main(string[] args)        {            //给委托传递具体方法            DoSomething myDelegate = new DoSomething(Student.MakeTea);            //委托被赋予了具体的方法            myDelegate();        }    }

我们来看一下我们定义的委托和委托被赋予的方法:

        public delegate void DoSomething();        public static void MakeTea() {             /..../         }

或许这样比较并看不出什么,毕竟我们对委托还没有具体的认识,所以我们来看一下委托的一些规定:
C#中委托的参数和返回类型,都要和你要具体委托的方法要一致。我们再来看一下委托时如何运作的:

            DoSomething myDelegate = new DoSomething(Student.MakeTea);             myDelegate();

或许有C++基础的已经看出来了,委托和C++中的函数指针类似。确实委托就可以看做一个函数指针。所以才会有委托的参数和返回值必须和具体委托的方法一致的规定。

多播委托

多播委托其实也很简单。我们先看代码:

    class Student {        public static void MakeTea() {            Console.WriteLine("Got it!");        }        public static void BuyPen() {            Console.WriteLine("On my way");        }    }    class Teacher    {        //声明一个委托        public delegate void DoSomething();        static void Main(string[] args)        {            //给委托传递具体方法            DoSomething myDelegate = new DoSomething(Student.MakeTea);            myDelegate += Student.BuyPen;            //委托被赋予了具体的方法            myDelegate();        }    }

我们看到Student中添加了一个BuyPen的功能,我们只是在程序中加了myDelegate += Student.BuyPen;
这就相当于要做两件事,显示倒茶,然后去买笔。其实是委托中重载了“+=”这个运算符,我们才可以以这种方法创建委托链。相对的我们可以用“-=”来销毁这个委托链。

事件

点击事件,加载事件充斥在我们的日常编程中,我们对事件都有一个模糊的认识。下面我们来看一下比较官方的概念:事件是类在发生其关注的事情时用来提供通知的一种方式。
我们先看一段代码:

 /// <summary>    /// 含有姓名和年龄属性,并重写了ToString方法    /// </summary>    class PersonEventArgs:EventArgs    {        string name;        int age;        public PersonEventArgs() { }        public PersonEventArgs(PersonEventArgs person) {            this.name = person.name;            this.age = person.age;        }        public PersonEventArgs(string name,int age) {            this.name = name;            this.age = age;        }        public override string ToString()        {            return string.Format("name is {0},age is {1}!",name,age);        }    }    //声明一个添加人员的委任    delegate void AddPersonEventHandle(object sender,PersonEventArgs args);    class AddPersonListener    {        //在委托的机制下我们建立一个添加事件        public event AddPersonEventHandle addPerson;        ArrayList personList = new ArrayList();        /// <summary>        /// 当我们向列表中添加一个对象时就触发该事件        /// </summary>        /// <param name="person"></param>        public void AddPerson(PersonEventArgs person) {            personList.Add(person);            //多路广播            addPerson += new AddPersonEventHandle(AddPersonListener_addpersonEvent);            //检测到监听的事件            OnAdd(person);        }        //具体委托的方法        void AddPersonListener_addpersonEvent(object sender, PersonEventArgs args)        {            Console.WriteLine(args.ToString());        }        //声明一个可以被重写的OnAdd的保护函数        public virtual void OnAdd(PersonEventArgs args) {            if (addPerson != null) {                addPerson(this, args);            }        }    }    class Program    {        static void Main(string[] args)        {            AddPersonListener listener = new AddPersonListener();            PersonEventArgs person = new PersonEventArgs("Joea");            listener.AddPerson(person);        }    }

上面的代码是实现一个我们向personList中添加一个对象时就把对象中的name打印出来。在其中我们定义个一个事件addPerson,关键字是event。在我们使用事件的时候,必须要声明对应的委托,而触发事件,其实就是在使用委托链。

最后我们有必要搞懂.Net Framework的编码规范:

  • 委托类型的名称都应该以 EventHandler结束。
  • 委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。
  • 事件的命名为 委托去掉 EventHandler之后剩余的部分。
  • 继承自EventArgs的类型应该以EventArgs结尾。
0 0
原创粉丝点击