委托和事件

一、委托

1.委托其本质是一个密封类,通俗易懂的理解就是委托可以将方法像参数一样进行自由传递(委托不可以定义在接口中),委托包含的只是方法的细节(也就是方法的签名);

2.可以将委托当作类来理解,当使用类时,我们首先要定义一个类,再实例化一个类,即创建类的一个对象。同样,使用委托也需要经过这样的过程。定义委托就是告诉编译器该委托代表了哪种类型的方法(通过方法签名确定),然后创建该委托的一个或多个实例;

3.理解委托的一种好方式是把委托当作给方法特征(签名)指定一个名称,也就是说任何一个方法(实例方法或静态方法),只要他的特征满足委托的定义,从理论上来说就可以通过这个委托来引用这个方法;

4.定义一个委托其实质就是定义一个新类(密封类)(委托是派生于基类System.Delegate的一个密封类),所以可以在定义类的任何地方定义委托,甚至可以在名称空间中把委托定义为顶层对象;

5.类创建的实例我们称之为“对象”,但是委托创建的实例,我们任然称之为委托;

6.委托在语法上总是带有一个参数构造函数,这个参数就是委托引用的方法,这个方法必须匹配最初定义委托时的签名;

7.委托既可以引用静态方法,又可以引用实例方法,只要方法的签名匹配委托的特征即可;

8.委托可以包含多个方法,这种委托称为委托链(多播委托);

9.委托可以识别+和+=运算符,他可以将方法添加到委托列表中,同样也可以识别-和-=运算符,他可以将方法从委托列表中移除,这是因为重写了+=和-=运算符;

10.有了委托就可以将方法当着参数来进行传递;

 

namespace EventDel
{
    //定义一个委托。委托可以定义在任意位置,包括定义在类的外面
    public delegate int AddDelegate(int a, int b);

    public class Program
    {
        static void Main(string[] args)
        {
            //实例化一个委托
            AddDelegate addDel = new AddDelegate(Decrease);           
            //委托调用。
            Console.WriteLine(addDel(2, 5));

            //以下两种方式都可以
            //addDel += new AddDelegate(Add);
            addDel += Add;
            //打印出-3和7,因为他依次执行了Decrease方法和Add方法
            Console.WriteLine(addDel(2, 5));
            //返回7,因为他将先执行的Decrease方法的返回值覆盖掉了
            int iResult = addDel(2, 5);

            //返回每一个委托方法的返回值
            Delegate[] delegateList = addDel.GetInvocationList();
            foreach (var list in delegateList)
            {
                object result = list.DynamicInvoke(8, 9);
                Console.WriteLine(result);
            }
            //将该委托从该委托列表移除
            addDel -= new AddDelegate(Decrease);
            Console.WriteLine(addDel(2, 5));

            //将方法当着参数传递给委托
            int iResultTest = Test.Sum(Add);
            Console.WriteLine(iResultTest);

            Console.ReadLine();
        }

        public static int Add(int a, int b)
        {
            return a + b;
        }

        public static int Decrease(int a, int b)
        {
            return a - b;
        }
    }

    public class Test
    {
        public static int Sum(AddDelegate addDel)
        {
            return addDel(7,9);
        }
    }
}

二、事件

1.C#中事件经常被用到,一提到事件必然会和委托有联系。例如,Button按钮的Click事件,我们不需要定义对应的委托,那是因为微软将他封装好了,我们只需要调用即可,但是自定义事件就必须要定义相应的委托;

2.C#中的事件遵循“发布——订阅”的设计模式,在这种模式中,一个类公布能够出现的事件,然后任意数量的类都可以预定这个事件,一旦事件产生,运行环境就负责通知每个订阅用户,告诉他们事件已经发生了,然后去执行对应的方法;

3.事件处理一般有一下几个步骤:

(1)、声明委托;

(2)、声明委托事件;

(3)、添加事件的触发方法,事件只能又事件发布者进行触发;

(4)、添加事件的响应方法;

(5)、将指定的事件响应方法邦定到要处理的事件上(订阅事件);

(6)、用户信息操作,触发事件(调用事件的触发方法);

(7)、通过事件委托的回调,执行我们需要的事件处理方法。

    /// <summary>
    /// 事件参数类
    /// </summary>
    public class TestEventArgs:EventArgs
    {
        #region Construtor

        public TestEventArgs(string content)
        {
            this.strContent = content;
        }

        #endregion

        #region Properties

        public string strContent
        {
            get;
            set;
        }

        #endregion
    }
    /// <summary>
    /// 事件发生类
    /// </summary>
    public class DefineEvent
    {
        #region Fields

        //定义委托
        public delegate void TestEventHandler(object obj, TestEventArgs e);

        //定义事件
        public event TestEventHandler OnReceive;

        #endregion

        #region Constructor

        public DefineEvent()
        {
        }

        #endregion

        #region  Methods

        public void StartEvent(TestEventArgs e)
        {
            //触发事件 只有事件的发布者才能触发事件
            OnReceive(this, e);
        }

        #endregion

    }
    /// <summary>
    /// 订阅事件类
    /// </summary>
    public class ReceiveEvent
    {
        #region  Contructor

        public ReceiveEvent(DefineEvent definEvent)
        {
            //订阅事件,只要满足该委托的方法都可以
            //definEvent.OnReceive += new DefineEvent.TestEventHandler(AnotherReceiveEvent.OnReceiveData);
            definEvent.OnReceive += new DefineEvent.TestEventHandler(OnReceiveData);
        }

        #endregion

        #region Methods

        public void OnReceiveData(object obj, TestEventArgs e)
        {
            Console.WriteLine("您输入的是:" + e.strContent);
        }

        #endregion
    }

    /// <summary>
    /// 另一个订阅事件类
    /// </summary>
    public class AnotherReceiveEvent
    {
        public AnotherReceiveEvent(DefineEvent definEvent)
        {
            definEvent.OnReceive += new DefineEvent.TestEventHandler(AnotherReceiveEvent.OnReceiveData);
        }

        public static void OnReceiveData(object obj, TestEventArgs e)
        {
            Console.WriteLine("您输入的内容是:" + e.strContent);
        }
    }
    public class Program
    {
        static void Main(string[] args)
        {
            string strContent = Console.ReadLine();
            if (!string.IsNullOrEmpty(strContent))
            {
                TestEventArgs testEventArgs = new TestEventArgs(strContent);
                DefineEvent defineEvent = new DefineEvent();
                //同一个事件可以被多个订户订阅,此处有两个类订阅了该事件
                ReceiveEvent receiveEvent = new ReceiveEvent(defineEvent);
                AnotherReceiveEvent test = new AnotherReceiveEvent(defineEvent);
                defineEvent.StartEvent(testEventArgs);             
            }

            Console.ReadLine();
        }
    }

三、委托和事件的关系

1.委托的本质是一个密封类,因此他可以像类一样在很多地方定义(如命名空间内、类内等)。而事件被编译成一个委托类型的变量,因此他只能定义在一个类里面;

2.委托是事件的基础,可以把事件看成是委托的一种代理;

3.事件只能由发布者进行触发,外部不能直接触发事件。

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值