打个比方,你外卖到了你不想动,叫你室友帮你去拿,然后你室友就帮你拿了。这就是委托,委托别人帮你做一件事情。
C#中的委托:
定义:delegate
语法: 权限修饰符 delegate 返回值 委托名 (参数类型 参数);
特别注意:被委托的方法有无返回值、返回值类型、有无参数、参数类型要与委托一致
实例:
class Program { //创建一个委托,不带参 delegate void myDelegate1(); //创建一个委托,带参带返回值 delegate int myDelegate2(int num); static void Main(string[] args) { //实例化委托 myDelegate1 d1 = new myDelegate1(one); myDelegate2 d2 = new myDelegate2(two); //或 //myDelegate1 d1 = one; //myDelegate2 d2 = two; //执行委托对象 d1(); int num = d2(123); Console.WriteLine("num = "+num); Console.ReadKey(); } static void one() { Console.WriteLine("one方法"); } static int two(int a) { Console.WriteLine("two方法"); return a; } }
委托中的多播
多播说白了,你把实例好的委托看成是一个队列或集合,+=看成是执行Add方法,-=看成是执行Remove方法,但如果你直接用 = 号那就相当于把这个方法直接赋值给了委托对象,会造成前面的添加进委托对象的方法被覆盖。
例子:
class Program { //创建一个委托,带参带返回值 delegate int myDelegate2(int num); static void Main(string[] args) { //实例化委托 myDelegate2 d2 = two; d2 += three; d2 += four; d2 += five; d2 -= four; //执行委托对象 int num = d2(123); Console.ReadKey(); } static void one() { Console.WriteLine("one方法"); } static int two(int a) { Console.WriteLine("two方法"); return a; } static int three(int a) { Console.WriteLine("three方法"); return a; } static int four(int a) { Console.WriteLine("four方法"); return a; } static int five(int a) { Console.WriteLine("five方法"); return a; } }
在代码里边,事件代表一类事情或者一个方法,一旦被触发就会执行,事件与触发器是一个整体。
C#中的事件:
定义:event
语法:权限修饰符 event 委托类 事件名;
例子:(例子中的发布器与订阅器可看为事件源与执行类)
namespace test_Delegate_Event { //创建一个委托 public delegate void myDelegate(); class Program { //触发事件 static void Main(string[] args) { //实例化发布器 Program2 p2 = new Program2(); //实例化订阅器 Program3 p3 = new Program3(p2); //执行发布器中的one方法 p2.one(); Console.ReadKey(); } } //发布器 class Program2 { //创建一个事件,相当于实例化委托 public event myDelegate myEvent; public void one() { Console.WriteLine("发布器中的one方法"); //执行触发器 if (myEvent!=null) { myEvent(); } } } //订阅器 class Program3 { //监视发布器类 Program2 p2; public Program3(Program2 p2) { this.p2 = p2; //向整个事件中添加要触发的方法 p2.myEvent += three; } public void two() { Console.WriteLine("订阅器中的two方法"); } } }如果你仔细看了程序的执行流程或者你可以在main方法上打上断点查看程序执行流程,你会发现:对于A类和B类,A类发布,B类订阅。就像是将B类的方法委托给A类执行(myEvent()),event更像是一个队列或集合,用来存放B类的方法(要被触发的方法)
为什么C#中的事务的定义要用到委托?
在官方文档的介绍中有这么一段描述:事件是一种特殊的多播委托。
那也就是说事件其实是委托的一种封装,事件的底层是委托。那好,为了证明这一点我们只用委托去实现整个事件与触发。
代码:
class Program { //触发事件 static void Main(string[] args) { Program2 p2 = new Program2(); //实例化订阅器 Program3 p3 = new Program3(p2); //执行发布器中的某个方法 p2.one(); Console.ReadKey(); } } //发布器 class Program2 { public delegate void myDelegate(); public myDelegate md = null; public void one() { Console.WriteLine("发布器中的one方法"); //执行委托 md(); } } //订阅器 class Program3 { public Program3(Program2 p2) { p2.md = two; } public void two() { Console.WriteLine("订阅器中的two方法"); } }如果你刚入C#的坑你没必要追究C#的设计者为什么要这样设计。你若很想了解,那就是为了解耦,减少代码量,提高代码效率,提高代码合理性。
事件的多播:
既然事件是一类特殊的多播委托,那么用法肯定雷同,不同的是事件不能用 = 。
namespace test_Delegate_Event { public delegate void myDelegate(); class Program { static void Main(string[] args) { Program2 p2 = new Program2(); Program3 p3 = new Program3(p2); p2.one(); Console.ReadKey(); } } //发布器 class Program2 { public event myDelegate myEvent; public void one() { Console.WriteLine("发布器中的one方法"); myEvent(); } } //订阅器 class Program3 { private Program2 p2; public Program3(Program2 p2) { this.p2 = p2; p2.myEvent += two; p2.myEvent += three; p2.myEvent += four; } public void two() { Console.WriteLine("订阅器中的two方法"); } public void three() { Console.WriteLine("订阅器中的three方法"); } public void four() { Console.WriteLine("订阅器中的four方法"); } } }