zoukankan      html  css  js  c++  java
  • C#中委托和事件的区别

    大致来说,委托是一个类,该类内部维护着一个字段,指向一个方法。事件可以被看作一个委托类型的变量,通过事件注册、取消多个委托或方法。本篇分别通过委托和事件执行多个方法,从中体会两者的区别。

    □ 通过委托执行方法

        class Program
    
        {
    
            static void Main(string[] args)
    
            {
    
                Example example = new Example();
    
                example.Go();
    
                Console.ReadKey();
    
            }
    
        }
    
    
    
        public class Example
    
        {
    
            public delegate void DoSth(string str);
    
    
    
            internal void Go()
    
            {
    
                //声明一个委托变量,并把已知方法作为其构造函数的参数
    
                DoSth d = new DoSth(Print);
    
    
    
                string str = "Hello,World";
    
    
    
                //通过委托的静态方法Invoke触发委托
    
                d.Invoke(str);
    
            }
    
    
    
            void Print(string str)
    
            {
    
                Console.WriteLine(str);
    
            }
    
        }
    

    以上,

    ○ 在CLR运行时,委托DoSth实际上就一个类,该类有一个参数类型为方法的构造函数,并且提供了一个Invoke实例方法,用来触发委托的执行。
    ○ 委托DoSth定义了方法的参数和返回类型
    ○ 通过委托DoSth的构造函数,可以把符合定义的方法赋值给委托
    ○ 调用委托的实例方法Invoke执行了方法

    但,实际上让委托执行方法还有另外一种方式,那就是:委托变量(参数列表)

        public class Example
    
        {
    
            public delegate void DoSth(object sender, EventArgs e);
    
    
    
            internal void Go()
    
            {
    
                //声明一个委托变量,并把已知方法作为其构造函数的参数
    
                DoSth d = new DoSth(Print);
    
    
    
                object sender = 10;
    
                EventArgs e = new EventArgs();
    
    
    
                d(sender, e);
    
            }
    
    
    
            void Print(object sender, EventArgs e)
    
            {
    
                Console.WriteLine(sender);
    
            }
    
        }
    

    以上,

    ○ 委托DoSth的参数列表和方法Print的参数列表还是保持一致
    ○ 委托DoSth中的参数object sender通常用来表示动作的发起者,EventArgs e用来表示动作所带的参数。

    而实际上,委托变量(参数列表),事件就是采用这种形式执行方法的。

    □ 通过事件执行方法

        public class Example
    
        {
    
            public delegate void DoSth(object sender, EventArgs e);
    
            public event DoSth myDoSth;
    
    
    
            internal void Go()
    
            {
    
                //声明一个委托变量,并把已知方法作为其构造函数的参数
    
                DoSth d = new DoSth(Print);
    
    
    
                object sender = 10;
    
                EventArgs e = new EventArgs();
    
    
    
                myDoSth += new DoSth(d);
    
                myDoSth(sender, e);
    
            }
    
    
    
            void Print(object sender, EventArgs e)
    
            {
    
                Console.WriteLine(sender);
    
            }
    
        }
    

    以上,

    ○ 声明了事件myDoSth,事件的类型是DoSth这个委托
    ○ 通过+=为事件注册委托
    ○ 通过DoSth委托的构造函数为事件注册委托实例
    ○ 采用委托变量(参数列表)这种形式,让事件执行方法

    而且,通过+=还可以为事件注册多个委托。

       public class Example
    
        {
    
            public delegate void DoSth(object sender, EventArgs e);
    
            public event DoSth myDoSth;
    
    
    
            internal void Go()
    
            {
    
                //声明一个委托变量,并把已知方法作为其构造函数的参数
    
                DoSth d = new DoSth(Print);
    
                DoSth d1 = new DoSth(Say);
    
    
    
                object sender = 10;
    
                EventArgs e = new EventArgs();
    
    
    
                //为事件注册多个委托
    
                myDoSth += new DoSth(d);
    
                myDoSth += new DoSth(d1);
    
    
    
                myDoSth(sender, e);
    
            }
    
    
    
            void Print(object sender, EventArgs e)
    
            {
    
                Console.WriteLine(sender);
    
            }
    
    
    
            void Say(object sender, EventArgs e)
    
            {
    
                Console.WriteLine(sender);
    
            }
    
        }
    

    以上,通过+=为事件注册1个或多个委托实例,实际上,还可以为事件直接注册方法。

        public class Example
    
        {
    
            public delegate void DoSth(object sender, EventArgs e);
    
            public event DoSth myDoSth;
    
    
    
            internal void Go()
    
            {
    
                object sender = 10;
    
                EventArgs e = new EventArgs();
    
    
    
                //为事件注册多个委托
    
                myDoSth += Print;
    
                myDoSth += Say;
    
    
    
                myDoSth(sender, e);
    
            }
    
    
    
            void Print(object sender, EventArgs e)
    
            {
    
                Console.WriteLine(sender);
    
            }
    
    
    
            void Say(object sender, EventArgs e)
    
            {
    
                Console.WriteLine(sender);
    
            }
    
        }    
    

    □ 通过EventHandler执行方法

    先来看EventHandler的源代码。

    1

    可见,EventHandler就是委托。现在就使用EventHandler来执行多个方法。

        public class Example
    
        {
    
            public event EventHandler myEvent;
    
    
    
            internal void Go()
    
            {
    
                object sender = 10;
    
                EventArgs e = new EventArgs();
    
    
    
                //为事件注册多个委托
    
                myEvent += Print;
    
                myEvent += Say;
    
    
    
                myEvent(sender, e);
    
            }
    
    
    
            void Print(object sender, EventArgs e)
    
            {
    
                Console.WriteLine(sender);
    
            }
    
    
    
            void Say(object sender, EventArgs e)
    
            {
    
                Console.WriteLine(sender);
    
            }
    
        }
    

    总结:
    ○ 委托就是一个类,也可以实例化,通过委托的构造函数来把方法赋值给委托实例
    ○ 触发委托有2种方式: 委托实例.Invoke(参数列表),委托实例(参数列表)
    ○ 事件可以看作是一个委托类型的变量
    ○ 通过+=为事件注册多个委托实例或多个方法
    ○ 通过-=为事件注销多个委托实例或多个方法
    ○ EventHandler就是一个委托

  • 相关阅读:
    GC(垃圾分代收集)
    排序算法总结
    Redis中的数据结构
    事务的隔离性(续篇)
    手写Spring mvc框架 (二)
    MySql日志与事务的隔离级别
    手写Spring mvc框架 (一)
    IO流
    随笔三(Ajax)
    关于博主noble_
  • 原文地址:https://www.cnblogs.com/kdp0213/p/8533588.html
Copyright © 2011-2022 走看看