当前位置:首页 > Windows程序 > 正文

c# delegate ,event

2024-03-31 Windows程序

首先说明,event其实也是一种delegate,为了区分,我们称一般的delegate为“plain delegate”。

写代码的过程中,经常会在delegate和event之间进行选择,以前也没仔细思考选择的原因,今天终于忍不住花了半天时间仔细琢磨了一下……好了,直接拿代码说话吧:

技术分享

using System;

技术分享


技术分享

namespace EventAndDelegate

技术分享

技术分享

技术分享

{

技术分享

    public delegate void TestDelegate(string s);

技术分享


技术分享

技术分享

    public interface ITest 

技术分享

{

技术分享

        // 【区别】 1. event可以用在interface中,而plain delegate不可以(因为它是field)

技术分享

        event TestDelegate TestE;   // Passed

技术分享

        TestDelegate TestD;         // Error: Interfaces cannot contain fields

技术分享

    }

技术分享


技术分享

技术分享

    public class Parent 

技术分享

{

技术分享

        public event TestDelegate TestE;

技术分享

        public TestDelegate TestD;

技术分享


技术分享

        protected void RaiseTestE(string s)

技术分享

技术分享

        

技术分享

{

技术分享

            TestE(s);   // The event ‘EventAndDelegate.Parent.TestE‘ can only

技术分享

                        // be used from within the type ‘EventAndDelegate.Parent‘

技术分享

        }

技术分享

    }

技术分享


技术分享

技术分享

    public class Child : Parent 

技术分享

{

技术分享

        void ChildFunc()

技术分享

技术分享

        

技术分享

{

技术分享

            // 【区别】 2. event不允许在声明它的class之外(即使是子类)被调用(除此之外只能用于+=或-=),而plain delegate则允许

技术分享

            TestD("OK");        // Passed

技术分享

            TestE("Failure");   // Error: The event ‘EventAndDelegate.Parent.TestE‘ can only appear on

技术分享

                                //        the left hand side of += or -= (except when used from within

技术分享

                                //        the type ‘EventAndDelegate.Parent‘)

技术分享


技术分享

            // 【补充】 在子类中要触发父类声明的event,通常的做法是在父类中声明一个protected的Raisexxx方法供子类调用

技术分享

            RaiseTestE("OK");   // The class ‘EventAndDelegate.Child‘ can only call the

技术分享

                                // ‘EventAndDelegate.ParentRaiseTestE‘ method to raise the event

技术分享

                                // ‘EventAndDelegate.Parent.TestE‘

技术分享


技术分享

            // 【区别】 同2#

技术分享

            object o1 = TestD.Target;

技术分享

            object o2 = TestE.Target;   // The class ‘EventAndDelegate.Child‘ can only call the

技术分享

                                        // ‘EventAndDelegate.ParentRaiseTestE‘ method to raise the event

技术分享

                                        // ‘EventAndDelegate.Parent.TestE‘

技术分享


技术分享

            // 【区别】 同2#

技术分享

            TestD.DynamicInvoke("OK");

技术分享

            TestE.DynamicInvoke("OK");   // The class ‘EventAndDelegate.Child‘ can only call the

技术分享

                                        // ‘EventAndDelegate.ParentRaiseTestE‘ method to raise the event

技术分享

                                        // ‘EventAndDelegate.Parent.TestE‘

技术分享

        }

技术分享

    }

技术分享


技术分享

    class Other

技术分享

技术分享

    

技术分享

{

技术分享

        static void Main(string[] args)

技术分享

技术分享

        

技术分享

{

技术分享

            Parent p = new Parent();

技术分享


技术分享

            p.TestD += new TestDelegate(p_Test1);   // Passed

技术分享

            p.TestE += new TestDelegate(p_Test1);   // Passed

技术分享


技术分享

            // 【区别】 3. event不允许使用赋值运算符,而plain delegate则允许。

技术分享

            //             注意,对plain delegate,使用赋值运算符意味着进行了一次替换操作!

技术分享

            p.TestD = new TestDelegate(p_Test2);   // Passed

技术分享

            p.TestE = new TestDelegate(p_Test2);   // Error: The event ‘EventAndDelegate.Parent.TestE‘ can only appear on

技术分享

                                                   //        the left hand side of += or -= (except when used from within

技术分享

                                                   //        the type ‘EventAndDelegate.Parent‘)

技术分享


技术分享

            // 【区别】 同2#

技术分享

            p.TestD("OK");      // Passed

技术分享

            p.TestE("Failure"); // Error: The event ‘EventAndDelegate.Parent.TestE‘ can only appear on

技术分享

                                //        the left hand side of += or -= (except when used from within

技术分享

                                //        the type ‘EventAndDelegate.Parent‘)

技术分享

        }

技术分享


技术分享

        static void p_Test1(string s)

技术分享

技术分享

        

技术分享

{

技术分享

            Console.WriteLine("p_Test1: " + s);

技术分享

        }

技术分享


技术分享

        static void p_Test2(string s)

技术分享

技术分享

        

技术分享

{

技术分享

            Console.WriteLine("p_Test2: " + s);

技术分享

        }

技术分享

    }

技术分享

}

技术分享


分析:

plain delegate与event的关系类似于field与Property(实事上前者就是field,或者我们可以把event看成是一种特殊的Property)

正是由于1#,在使用上,plain delegate几乎没有任何限制,而event则有严格的限制(只能用在+=和-=的左边)

结论

event更面向对象一些。

当我们需要灵活时,直接使用plain delegate;反之,需要严格的控制时,,使用event。

由于event不能使用赋值运算符,因此有时我们要求一个事件在任何时刻只能有一个响应方法时,我们使用plain delegate更为方便。 

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/39112.html

Jm-杰米博客Jamie
草根站长的技术交流乐园!IT不会不要紧快来好好学习吧!
  • 20786文章总数
  • 7494595访问次数
  • 建站天数
  • 友情链接