zoukankan      html  css  js  c++  java
  • C#中委托的理解

      请注意,这只是个人关于C#中委托的一点点理解,参考了一些博客,如有不周之处,请指出,谢谢!

      委托是一种函数指针,委托是方法的抽象,方法是委托的实例。委托是C#语言的一道坎,明白了委托才能算是C#真正入了门。委托在c#中的应用特别的多,最常见比如事件监听器就是利用委托来实现的。我们点击winform上面的一个按钮,系统就会响应,这其实就是委托。

      为什么要用委托呢?绝对不是为了简单问题复杂化。我们知道在程序设计当中,数据结构和算法是非常重要的,但是在实际的开发当中,我们好像又不太用的着这些东西,这是因为我们使用的都是高级语言,想java、c#这一类的。这些高级语言在设计的时候已经帮我们把这些问题考虑进去了,所以我们才感觉不到算法和数据结构的存在。举个最简单的例子,我们常用的List、HshTable之类的都是java帮我们定义好了的数据结构。委托也是这样。委托的存在本质上是为了让代码解耦,实现代码的可维护和可扩展。

      我们就以点击一个按钮,然后触发一个事件为例来说明。

    public void btnConfirmOnClick()
    {
        FunctionA();
        FunctionB();
    }

    在上面的这段代码中,当一个按钮被点击的时候,就会去主动地调用FunctionA();FunctionB();这两个方法,这就完成了我们的任务啊。但是,当用户的需求发生见二连三的改变的时候,上面的代码就会被频繁的改动,比如说,要新增加一个FunctionC(),这样一来,说明上面这段代码距离工程实践的要求还有一定的距离。按照23种设计原则的要求,当代码的耦合性太大的时候,就要对代码进行拆分,怎么拆分呢?就是引入一个新的类C,当按钮被点击的时候,btnConfirmOnClick()这个方法去通知类C,C再去调用FunctionA();FunctionB();这些方法,这其实就是委托的设计思想。

      下面是一段委托的代码。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace DelegateTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                A a = new A(); // 定义按钮A
    
                B b = new B(a); // 定义响应事件B
    
                C c = new C(a); // 定义响应事件C
    
                // 按钮A被单击
                a.Raise("单击");
    
                // 按钮A被双击
                //a.Raise("双击");
    
                // 按钮A被三连击
                //a.Fall();
    
                Console.ReadLine();
                // 由于B和C订阅了A的事件,所以无需任何代码,B和C均会按照约定进行动作。
            }
        }
    
        /// <summary>
        /// 按钮A点击委托
        /// </summary>
        /// <param name="hand">点击:单击、双击</param>
        public delegate void RaiseEventHandler(string hand);
        /// <summary>
        /// 按钮A被三连击委托
        /// </summary>
        public delegate void FallEventHandler();
        /// <summary>
        /// 按钮A
        /// </summary>
        public class A
        {
            /// <summary>
            /// 按钮A点击事件
            /// </summary>
            public event RaiseEventHandler RaiseEvent;
            /// <summary>
            /// 按钮A被三连击事件
            /// </summary>
            public event FallEventHandler FallEvent;
    
            /// <summary>
            /// 点击
            /// </summary>
            /// <param name="hand">手:单击、双击</param>
            public void Raise(string hand)
            {
                Console.WriteLine("按钮A{0}点击", hand);
                // 调用点击事件,传入单击或双击手作为参数
                if (RaiseEvent != null)
                {
                    RaiseEvent(hand);
                }
            }
            /// <summary>
            /// 被三连击
            /// </summary>
            public void Fall()
            {
                Console.WriteLine("按钮A被三连击");
                // 调用被三连击事件
                if (FallEvent != null)
                {
                    FallEvent();
                }
            }
        }
        /// <summary>
        /// 响应事件B
        /// </summary>
        public class B
        {
            A a;
    
            public B(A a)
            {
                this.a = a;
                a.RaiseEvent += new RaiseEventHandler(a_RaiseEvent); // 订阅点击事件
                a.RaiseEvent += new RaiseEventHandler(a_RaiseEvent); // 订阅点击事件
                a.FallEvent += new FallEventHandler(a_FallEvent); // 订阅被三连击事件
            }
            /// <summary>
            /// 按钮点击时的动作
            /// </summary>
            /// <param name="hand">若按钮A被单击,则B攻击</param>
            void a_RaiseEvent(string hand)
            {
                if (hand.Equals("单击"))
                {
                    Attack();
                }
            }
    
            /// <summary>
            /// 按钮被三连击时的动作
            /// </summary>
            void a_FallEvent()
            {
                Attack();
            }
    
            /// <summary>
            /// 攻击
            /// </summary>
            public void Attack()
            {
                Console.WriteLine("响应事件B响应");
            }
        }
        /// <summary>
        /// 响应事件C
        /// </summary>
        public class C
        {
            A a;
            public C(A a)
            {
                this.a = a;
                a.RaiseEvent += new RaiseEventHandler(a_RaiseEvent); // 订阅点击事件
                a.FallEvent += new FallEventHandler(a_FallEvent); // 订阅被三连击事件
            }
            /// <summary>
            /// 按钮点击时的动作
            /// </summary>
            /// <param name="hand">若按钮A被双击,则攻击</param>
            void a_RaiseEvent(string hand)
            {
                if (hand.Equals("双击"))
                {
                    Attack();
                }
            }
    
            /// <summary>
            /// 按钮被三连击时的动作
            /// </summary>
            void a_FallEvent()
            {
                Attack();
            }
            /// <summary>
            /// 攻击
            /// </summary>
            public void Attack()
            {
                Console.WriteLine("响应事件C响应");
            }
        }
    
    }
  • 相关阅读:
    Yarn和Mesos:资源管理调度平台
    链接、装载、库
    PostgreSQL查询优化简介
    STL内存管理
    jemalloc总结
    ptmalloc总结
    数据库查询优化
    Linux交换空间和内存不足
    Linux内存管理
    HBase:分布式列式NoSQL数据库
  • 原文地址:https://www.cnblogs.com/1102whw/p/7679263.html
Copyright © 2011-2022 走看看