委托与事件的联系和区别

委托和事件是两种类型,而字段和属性是具体的对象,虽然都是封装,但两者之间还是有区别的,事件对委托的封装是在类级别的、抽象层次、稳定的封装,而属性对字段的封装是在对象级别的、具体的、可定义的封装。

MSDN中有这么一句:“事件是特殊类型的多路广播委托,仅可从声明它们的类或结构(发行者类)中调用。”如此看来事件与委托的关系应该是继承关系,在继承的过程中在EventHandler类中进行的封装。


用代码来比较委托和事件,分别用事件和委托来实现实现一个非常简单的功能:控制台输入一个数,如果输入100的话就显示"Game Over"。

事件实现代码:

        static void Main(string[] args)
        {
            //事件实现
            Game1 game = new Game1();
            game.GameOverEvent += game_GameOver;

            while (true)
            {
                Console.WriteLine("输入:");

                game.Scroe = Convert.ToInt32(Console.ReadLine());
            }
        }
static void game_GameOver(object sender, EventArgs e)
        {
            Console.WriteLine("Game Over");
        }

        static void game_GameOver()
        {
            Console.WriteLine("Game Over");
        }
 //事件实现
    class Game1
    {
        //event 关键字用于在发行者类中声明事件。
        public event EventHandler GameOverEvent;

        private int scroe;

        public int Scroe
        {
            get { return scroe; }
            set
            {
                this.scroe = value;
                if (this.GameOverEvent != null)
                {
                    if (value == 100)
                    {
                        this.GameOverEvent(this, new EventArgs());//触发事件
                    }
                }
            }
        }
    }

委托实现代码:

    class Program
    {
        static void Main(string[] args)
        {
            //委托实现
            Game2 game = new Game2();
            game.AddMethod(game_GameOver);

            while (true)
            {
                Console.WriteLine("输入:");

                game.Scroe = Convert.ToInt32(Console.ReadLine());
            }
        }

        static void game_GameOver(object sender, EventArgs e)
        {
            Console.WriteLine("Game Over");
        }

        static void game_GameOver()
        {
            Console.WriteLine("Game Over");
        }
    }
    //委托实现
    class Game2
    {
        public delegate void OverDelegate();

        //将委托声明为private,防止订阅者直接调用,使用new等功能
        private OverDelegate GameOverDelegate;

        //AddMethod和RemoveMethod模拟事件的+=和-=赋值
        public void AddMethod(OverDelegate over)
        {
            this.GameOverDelegate += over;
        }

        public void RemoveMethod(OverDelegate over)
        {
            this.GameOverDelegate -= over;
        }

        private int scroe;

        public int Scroe
        {
            get { return scroe; }
            set
            {
                this.scroe = value;
                if (this.GameOverDelegate != null)
                {
                    if (value == 100)
                    {
                        this.GameOverDelegate();//触发委托
                    }
                }
            }
        }
    }
Game1在此就是发布者类,对事件GameOverEvent的封装还是在发布者类中完成的,并不是在EventHandler类中就已经完成。这种封装模式和属性对字段的封装模式是完全一样的,只不过这个封装过程是由于有了event关键字在编译阶段由编译器自动完成的,在发布者类中将EventHandler类型的GameOverEvent委托设为私有,并加上Add和Remove方法,和上面用委托模拟的事件是一样的,也就是事件的本质就是在小标题2中用委托模拟的事件。这么说来,事件对委托的封装是可以类比为属性对字段的封装的,如果说有区别,那就是前者是编译阶段完成的、不可自定义的封装,后者是coding阶段实现的、可自定义的封装,但它们都是在对象级别完成的。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值