委托与事件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了委托与事件相关的知识,希望对你有一定的参考价值。

委托在底层就是一个函数的指针,委托是事件的基础。

 

 

你可以传递引用类型、值类型、但是你有没有需要传一个方法呢?传方法的过程就是委托。

消息类:

 public class Message
    {
        /// <summary>
        /// 传引用类型
        /// </summary>
        /// <param name="msg"></param>
        public static void Send(string msg)
        {
            Console.WriteLine("你传递的参数是string:{0}", msg);
        }

        /// <summary>
        /// 传值类型
        /// </summary>
        /// <param name="msg"></param>
        public static void Send(int msg)
        {
            Console.WriteLine("你传递的参数是int:{0}", msg);
        }

        /// <summary>
        /// 利用委托传一个方法过来
        /// </summary>
        /// <param name="msg"></param>
        public static void Send(Action msg)
        {
            ///执行它
            msg.Invoke();
         //   Console.WriteLine("你传递的参数是int:{0}", msg);
        }
    }

 

使用例子:

 class Program
    {
        static void Main(string[] args)
        {
            ///传引用类型的字符串
            Message.Send("晚上好!端午节快乐!");

            ///传值类型的,int 68
            Message.Send(68);

            ///传一个方法
            Message.Send(SendMessage);

            Console.ReadKey();

        }

        /// <summary>
        /// 方法
        /// </summary>
        static void SendMessage()
        {
            Console.WriteLine("我是 Program 类的 SendMessage 方法");
        }
    }

运行结果:

 

是不是很有用处:

当两个对象之间的处理结果需要相互通知。(onClick,onLoad等一切的事件,基础都是基于委托),委托实际就是一个观察者模式。其作用是两个对象之间可以通过委托,相互通知消息。

 

委托的定义:

    public class DelegateExample
    {

        /// <summary>
        /// 定义一个方法,方法有0到N个参数,可以有返回值,和无返回值
        /// </summary>
        /// <param name="msg"></param>
        public void MethodTest(int Ivalue) { }

        /// <summary>
        /// 定义另一个委托,委托和方法一样有0到N个参数,可以有返回值,和无返回值
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="msg2"></param>
        public delegate int DelegateTest(string msg, string msg2);

        public void Show()
        {
            ///定义委托:委托像 “类” 一样,定义来使用,用 new DelegateTest 来指向方法 
            DelegateTest delegateTest1 = new DelegateTest(DelegateTest2_Mothod);

            ///调用委托:将参数给定
            delegateTest1.Invoke("aa", "bb");
            Console.WriteLine("------------------------------------");
            ///直接指向方法
            DelegateTest delegateTest2 = DelegateTest2_Mothod;
            ///不用 Invoke 也可以直接使用
            delegateTest1("cc", "dd");

            Console.WriteLine("------------------------------------");

            ///用 Lambda 表达式来定义一个匿名方法 
            DelegateTest delegateTest3 = (string msg, string msg2) => { Console.WriteLine("BeginInvoke"); return msg.Length + msg2.Length; };

            ///异步来调用
            delegateTest3.BeginInvoke("ee", "ff", null, null);
            Console.WriteLine("------------------------------------");
            ///用 Lambda 表达式来定义一个匿名方法 
            DelegateTest delegateTest4 = (string msg, string msg2) => { Console.WriteLine("执行委托"); return msg.Length + msg2.Length; };

            ///多次指定方法(多播委托)
            delegateTest4 += (string msg, string msg2) => { Console.WriteLine("执行委托"); return msg.Length + msg2.Length; };

            delegateTest4 += DelegateTest2_Mothod;

            delegateTest4 += DelegateTest2_Mothod;
            ///减掉一个
            delegateTest4 -= DelegateTest2_Mothod;

            ///减掉一个匿名委托,实际是不起作用的,因为匿名没有“固定”指向名称,所以不能减掉,下面同样会执行
            delegateTest4 -= (string msg, string msg2) => { Console.WriteLine("执行委托"); return msg.Length + msg2.Length; };

            delegateTest4.Invoke("dd", "eee");
        }

        int DelegateTest2_Mothod(string msg, string msg2)
        {
            Console.WriteLine("执行委托");
            return msg.Length + msg2.Length;
        }

    }

 

执行结果是:

 

delegateTest1  直接用(delegateTest1("cc", "dd");),Invoke调用,delegateTest1.Invoke("aa", "bb");两次结果完全相同

delegateTest3 begininvoke 是在前面的,结果跑到最后面。异步的原因。

delegateTest4 加了4次委托,减掉2次,但是执行3次,说明了有一次没有减掉。就是匿名没有减掉。

 

记住委托的作用就是,定义一个方法(函数)的指针。

 

在编程中,委托是一个非常有用的功能,因为任何异步调用的基础也是委托

 

.net 框架为我们定义好了两个委托,一个有返回值,一个无返回值,这样我们就免于需要创建委托的重复劳动:

无返回

Action
Action<string>
0-16个参数,无返回值

在系统当中大量使用


有返回

func<int>
fun<string,int> 第一个是参数,最后是返回值
1-17,前面是参数,最后一个是返回值

在系统当中大量使用

 

1、异步必须要用委托
2、方法像类型一样传递,可以分离业务逻辑

 

事件的基础就是委托:

事件在系统中使用的非常之多。

 定义一个事件:

        /// <summary>
        ///  定义一个事件
        /// </summary>
        public event Action<string> SendEvent;

 

事件的使用:

        static void Main(string[] args)
        {
            ///传引用类型的字符串
            Message.Send("晚上好!端午节快乐!");

            ///传值类型的,int 68
            Message.Send(68);

            ///传一个方法
            Message.Send(SendMessage);


            DelegateExample delegateExample = new DelegateExample();
            delegateExample.Show();

            ///实例化事件类
            MyEvent myevent = new MyEvent();

            ///订阅事件
            myevent.SendEvent += Myevent_SendEvent;

            ///执行工作
            myevent.Send(string.Format("开始:{0}", DateTime.Now));

            Console.ReadKey();

        }

        /// <summary>
        /// 订阅的处理方法(确定委托需要指针,指向的方法)
        /// </summary>
        /// <param name="obj"></param>
        private static void Myevent_SendEvent(string obj)
        {
            Console.WriteLine("返回:{0}", obj);
        }

 

事件演示代码:

  public class MyEvent
    {

        /// <summary>
        /// 方法的定义
        /// </summary>
        /// <param name="msg"></param>
        public void MethodDemo(string msg)
        { }

        /// <summary>
        /// 委托的定义,委托在方法修饰符后面加 delegate
        /// 委托没有实体{}
        /// </summary>
        /// <param name="msg"></param>
        public delegate void delegateDemo(string msg);


        /// <summary>
        /// 事件的定义,事件在委托修饰符后面加 event
        /// </summary>
        public event delegateDemo eventDemo;

        /// <summary>
        /// 
        /// 记住,事件必须以一个委托为基础
        ///  定义一个事件,本例中以系统自带的 Action 为基础
        ///  
        /// </summary>
        public event Action<string> SendEvent;

        public void Send(string msg)
        {

            Task.Factory.StartNew(() =>
            {

                Thread.Sleep(TimeSpan.FromSeconds(15));

                ///
                if (SendEvent != null)
                {
                    SendEvent(string.Format("Task.Factory.StartNew:{0},{1}", DateTime.Now, msg));
                }
            });


        }

    }

 

运行结果:

 

委托是一种类型、是一个函数指针、事件就是委托的一个实例

委托加上一个 EVENT 关键字后就变成了事件

事件不能直接赋值。也不能被调用。只能通过+=,-= 来操作委托

委托就是 观察者模式 的实现方法

委托是业务之间逻辑剥离的解决方案。

 

以上是关于委托与事件的主要内容,如果未能解决你的问题,请参考以下文章

C#编程之委托与事件四

代理模式与AOP

C#事件与委托详解

代理模式

Java动态代理与Cglib库

委托与事件小demo