委托
委托是C#1.0提出的一种功能,如今C#都将更新到C#10.0了(最新8.0),对委托的用法还只是停留在原地,略等于不知道。今天自己来学习,解锁下“委托”这个技能,本文综合圈子各位大佬的文章总结而来,若有错误或不足,欢迎斧正。
委托在.net framwork中的应用非常广泛(CS项目中经常用到,BS项目相对要少点);本文将讲述委托的概念(什么是委托 What)、委托的作用(为什么要使用委托 Why)、委托怎么用(How);
委托的概念-WHAT:
委托:把事情托付给别人或别的机构(办理)(百度百科释义:https://baike.baidu.com/item/%E5%A7%94%E6%89%98/34711?fr=aladdin);直观点就是,本该自己做的事情,交给别人做;
C#中的委托:委托实际为一种 中间人 ,A需要C去做某件事情 而由B去调用C来做事。委托是用户自定义的类,它定义了方法的类型。储存的是一系列具有相同参数和返回类型方法的地址列表,调用委托时,此委托列表的所有方法都将被执行。总的来说:委托是方法的抽象,它代表了一组方法的共同特征。
委托的作用-WHY:
用来实现传递回调函数;将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。
委托的用法-HOW:
1:先声明定义一个委托
2:实例化一个委托,实例化的时候需要绑定方法(绑定的方法必须与定义的委托具有相同参数列表和返回值,否则编辑器会报错)
3:调用委托
- 定义委托的关键词:delegate
- 委托是一种类型,它可以声明在类的外部,也可以在类的内部声明;
using System; using System.Collections.Generic; using System.Text; namespace Tools { public delegate void MyDelegateOutClass();//类外部申请一个委托 public class LearnDelegate { public delegate void MyDelegateInClass();//类内部申请一个委托 } }
- 示例一:无参数、无返回值委托和方法绑定
public class LearnDelegate { //1:声明一个无参数无返回值的委托 public delegate void MyDelegateNoParmNoreturn();public static void Run() { //1:无参数无返回值的委托实例化与调用 MyDelegateNoParmNoreturn method1 = new MyDelegateNoParmNoreturn(NoParmsNoReturns); method1.Invoke(); } public static void NoParmsNoReturns() { Console.WriteLine("这是一个无参数、无返回值的方法"); } }
从示例一可以看出:委托的实例化和类的实例化相似:在使用委托的时候,你可以像对待一个类一样对待它。即1:先声明:2:再实例化。只是有点不同,类在实例化之后叫对象或实例,但委托在实例化后仍叫委托;委托的实例化需要绑定方法,也就是委托要办的事情
- 示例二:有参数无返回值委托和方法绑定
public class LearnDelegate { //1:声明一个无参数无返回值的委托 public delegate void MyDelegateNoParmNoreturn(); //2:声明一个有参数无返回值的委托 public delegate void MyDelegateHasParmsNoReturn(string name, string sex); public static void Run() { //1:无参数无返回值的委托实例化与调用 MyDelegateNoParmNoreturn method1 = new MyDelegateNoParmNoreturn(NoParmsNoReturns); method1.Invoke(); //2:有参数无返回值的委托实例化与调用 MyDelegateHasParmsNoReturn method2 = new MyDelegateHasParmsNoReturn(HasParmsNoReturns); method2("zhangsan", "男"); } public static void NoParmsNoReturns() { Console.WriteLine("这是一个无参数、无返回值的方法"); } public static void HasParmsNoReturns(string _name) { Console.WriteLine("这是一个有参数、无返回值的方法"); } }
- 示例三:有参数、有返回值的委托和方法绑定
public class LearnDelegate { //1:声明一个无参数无返回值的委托 public delegate void MyDelegateNoParmNoreturn(); //2:声明一个有参数无返回值的委托 public delegate void MyDelegateHasParmsNoReturn(string name, string sex); //3声明一个有参数有返回值的委托 public delegate string MyDelegateHasParmsHasReturn(string name); public static void Run() { //1:无参数无返回值的委托实例化与调用 MyDelegateNoParmNoreturn method1 = new MyDelegateNoParmNoreturn(NoParmsNoReturns); method1.Invoke(); //2:有参数无返回值的委托实例化与调用 MyDelegateHasParmsNoReturn method2 = new MyDelegateHasParmsNoReturn(HasParmsNoReturns); method2("zhangsan", "男"); //3:有参数有返回值的委托实例化与调用 MyDelegateHasParmsHasReturn method3 = new MyDelegateHasParmsHasReturn(HasParmsHasReturns); var name = method3("lisi"); } public static void NoParmsNoReturns() { Console.WriteLine("这是一个无参数、无返回值的方法"); } public static void HasParmsNoReturns(string _name) { Console.WriteLine("这是一个有参数、无返回值的方法"); } public static string HasParmsHasReturns(string _name) { Console.WriteLine("这是一个有参数、有返回值的方法"); return ""; } public static void HasParmsNoReturns(string _name, string _sex) { Console.WriteLine("这是一个有两个参数、无返回值的方法"); } }
- 自带委托Action
- Action为C#自带的委托类型,无需另外声明委托,可直接创建一个委托实例
- Action为无返回值的委托类型
public static void HasParmsNoReturns(string _name, string _sex) { Console.WriteLine("这是一个有两个参数、无返回值的方法"); } public static void ShowAction() { Action action = new Action(NoParmsNoReturns); action(); //委托实例调用 => action.Invoke(); Action<string,string> action2 = new Action<string,string>(HasParmsNoReturns); action2("","");//有参数 无返回值,此时参数类型必须标明在声明委托中 }
- 自带委托 Func
- Func 为C#自带的委托类型,无需另外声明委托,可直接创建一个委托实例
- Func 为有返回值的委托类型
public static string HasParmHasReturn(string name,string address,string email) { return "hello world"; } public static void ShowFunc() { Func<string> fun1 = new Func<string>(NoParmHasReturn); fun1();//无参数,有返回值 Func<string, string, string,string> fun2 = new Func<string, string, string,string>(HasParmHasReturn); fun2("","",""); //有参数,有返回值 }
注意:当Func中只有一个参数,说明需要绑定的是无参数的有返回值的方法,Func的唯一参数为返回值类型;
Func中的参数类型、返回值类型都需要标明,在泛型类声明中,当有返回值得时候,最后一个参数类型为返回值类型
参数我们试下将方法的返回值类型改为int,编译报错;
正确写法:
public static int HasParmHasReturn(string name,string address,string email) { return 123; } public static void ShowFunc() { Func<string> fun1 = new Func<string>(NoParmHasReturn); fun1(); Func<string, string, string,int> fun2 = new Func<string, string, string,int>(HasParmHasReturn); fun2("","",""); }
- 多播委托
- 只需要调用一个委托,就可以一次执行这个委托中包含的所有方法(一个委托能够指向多个函数方法)
- 多播委托引用的函数的返回类型必须是void,否则,我们只能得到最后一个函数调用结果。
使用示例:
/// <summary> /// 多播委托使用示例 /// </summary> public static void ShowMore() { Action action = Show1; action += Show2; action += Show3; action += Show4; action -= Show3; action += Show3; action(); Console.ReadLine(); } public static void Show1() { Console.WriteLine("show T1"); } public static void Show2() { Console.WriteLine("show T2"); } public static void Show3() { Console.WriteLine("show T3"); } public static void Show4() { Console.WriteLine("show T4"); }
看到示例,可能会有点懵;我们先看下运行结果,在作分析:
其中有
- 委托名=方法名 :实例化委托赋值语法的简写
- “+=方法名” :委托绑定方法,将相同参数列表的函数绑定到统一委托中执行
- “-=方法名” :取消委托绑定的方法,将方法从委托方法列表中移除
这个是委托实例化的简写 即
MyDelegateNoParmNoreturn method1 = new MyDelegateNoParmNoreturn(NoParmsNoReturns); //等效于 MyDelegateNoParmNoreturn method1 = NoParmsNoReturns;
注:第一次用的“=”,是赋值的语法;第二次,用的是“+=”,是绑定的语法。如果第一次就使用“+=”,将出现“使用了未赋值的局部变量”的编译错误。
然后我们来看多播委托的执行过程:
首先我们用了C#自带的无返回值的Action,赋值了一个Show1的方法;然后为该委托绑定了Show2、Show3、Show4的方法;再然后取消了Show3的绑定,最后又重新绑定了Show3;所以该委托依次执行结果为:show T1 、show T2、show T3(后被移除不输出)、showT4、showT3(重新绑定ShowT3,最后输出)
总结:使用委托可以将多个方法绑定到同一个委托变量,当调用此委托,可以依次调用所有绑定的方法