C#中的委托与事件

委托

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

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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值