请注意,这只是个人关于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响应"); } } }