简单理解C#中的委托(delegate)与事件(event)

什么是委托?

打个比方,你外卖到了你不想动,叫你室友帮你去拿,然后你室友就帮你拿了。这就是委托,委托别人帮你做一件事情。

C#中的委托:

定义:delegate

语法: 权限修饰符 delegate 返回值 委托名 (参数类型 参数);

特别注意:被委托的方法有无返回值、返回值类型、有无参数、参数类型要与委托一致

实例:

class Program
    {
        //创建一个委托,不带参
        delegate void myDelegate1();
        //创建一个委托,带参带返回值
        delegate int myDelegate2(int num);
        static void Main(string[] args)
        {
            //实例化委托
            myDelegate1 d1 = new myDelegate1(one);
            myDelegate2 d2 = new myDelegate2(two);
            //或
            //myDelegate1 d1 = one;
            //myDelegate2 d2 = two;
            //执行委托对象
            d1();
            int num = d2(123);
            Console.WriteLine("num = "+num);
            Console.ReadKey();
        }
        static void one() {
            Console.WriteLine("one方法");
        }
        static int two(int a) {
            Console.WriteLine("two方法");
            return a;
        }
    }

 

委托中的多播

多播说白了,你把实例好的委托看成是一个队列或集合,+=看成是执行Add方法,-=看成是执行Remove方法,但如果你直接用 = 号那就相当于把这个方法直接赋值给了委托对象,会造成前面的添加进委托对象的方法被覆盖。

例子:

class Program
    {
        //创建一个委托,带参带返回值
        delegate int myDelegate2(int num);
        static void Main(string[] args)
        {
            //实例化委托
            myDelegate2 d2 = two;
            d2 += three;
            d2 += four;
            d2 += five;
            d2 -= four;
            //执行委托对象
            int num = d2(123);
            Console.ReadKey();
        }
        static void one() {
            Console.WriteLine("one方法");
        }
        static int two(int a) {
            Console.WriteLine("two方法");
            return a;
        }
        static int three(int a)
        {
            Console.WriteLine("three方法");
            return a;
        }
        static int four(int a)
        {
            Console.WriteLine("four方法");
            return a;
        }
        static int five(int a)
        {
            Console.WriteLine("five方法");
            return a;
        }
    }

 

什么是事件?

在代码里边,事件代表一类事情或者一个方法,一旦被触发就会执行,事件与触发器是一个整体。

C#中的事件:

定义:event

语法:权限修饰符 event 委托类 事件名;

例子:(例子中的发布器与订阅器可看为事件源与执行类)

namespace test_Delegate_Event
{
    //创建一个委托
    public delegate void myDelegate();
    class Program
    {
        //触发事件
        static void Main(string[] args)
        {
            //实例化发布器
            Program2 p2 = new Program2();
            //实例化订阅器
            Program3 p3 = new Program3(p2);
            //执行发布器中的one方法
            p2.one();
            Console.ReadKey();
        }
    }
    //发布器
    class Program2
    {
        //创建一个事件,相当于实例化委托
        public event myDelegate myEvent;
        public void one() {
            Console.WriteLine("发布器中的one方法");
            //执行触发器
            if (myEvent!=null) {
                myEvent();
            }
        }
    }
    //订阅器
    class Program3
    {
        //监视发布器类
        Program2 p2;
        public Program3(Program2 p2) {
            this.p2 = p2;
            //向整个事件中添加要触发的方法
            p2.myEvent += three;
        }

        public void two() {
            Console.WriteLine("订阅器中的two方法");
        }
    }
}

如果你仔细看了程序的执行流程或者你可以在main方法上打上断点查看程序执行流程,你会发现:对于A类和B类,A类发布,B类订阅。就像是将B类的方法委托给A类执行(myEvent()),event更像是一个队列或集合,用来存放B类的方法(要被触发的方法)

 

为什么C#中的事务的定义要用到委托?

在官方文档的介绍中有这么一段描述:事件是一种特殊的多播委托。

那也就是说事件其实是委托的一种封装,事件的底层是委托。那好,为了证明这一点我们只用委托去实现整个事件与触发。

代码:

class Program
    {
        //触发事件
        static void Main(string[] args)
        {
            Program2 p2 = new Program2();
            //实例化订阅器
            Program3 p3 = new Program3(p2);
            //执行发布器中的某个方法
            p2.one();
            Console.ReadKey();
        }
    }
    //发布器
    class Program2
    {
        public delegate void myDelegate();
        public myDelegate md = null;
        public void one() {
            Console.WriteLine("发布器中的one方法");
            //执行委托
            md();
        }
    }
    //订阅器
    class Program3
    {
        public Program3(Program2 p2) {
            p2.md = two;

        }

        public void two() {
            Console.WriteLine("订阅器中的two方法");
        }
    }

如果你刚入C#的坑你没必要追究C#的设计者为什么要这样设计。你若很想了解,那就是为了解耦,减少代码量,提高代码效率,提高代码合理性。

 

事件的多播:

既然事件是一类特殊的多播委托,那么用法肯定雷同,不同的是事件不能用 = 。

namespace test_Delegate_Event
{
    public delegate void myDelegate();
    class Program
    {
        static void Main(string[] args)
        {
            Program2 p2 = new Program2();
            Program3 p3 = new Program3(p2);
            p2.one();
            Console.ReadKey();
        }
    }
    //发布器
    class Program2
    {
        public event myDelegate myEvent;
        public void one() {
            Console.WriteLine("发布器中的one方法");
            myEvent();
        }
    }
    //订阅器
    class Program3
    {
        private Program2 p2;
        public Program3(Program2 p2) {
            this.p2 = p2;
            p2.myEvent += two;
            p2.myEvent += three;
            p2.myEvent += four;
        }

        public void two() {
            Console.WriteLine("订阅器中的two方法");
        }
        public void three() {
            Console.WriteLine("订阅器中的three方法");
        }
        public void four()
        {
            Console.WriteLine("订阅器中的four方法");
        }
    }
}

 

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值