C# 泛型委托和多播委托
泛型委托的定义
泛型委托的作用可以使程序定义一个委托,满足多个需求,如需要定义一个int类型参数的委托和定义一个string类型类型的委托时,直接使用泛型,就可以减少多次定义委托
泛型委托定义时候只需要再方法名后加:<类型在方法中的名字>
类型可以是多个,多个类型之间用 ”,“ 逗号隔开
// 定义泛型委托 delegate void MyDelegate<T>(T str); // 定义返回值为泛型的委托 delegate Y MyDelegate1<T, Y>(T str); // 实例化泛型委托 MyDelegate<string> md = (str) => { Console.WriteLine("泛型委托"); Console.WriteLine("参数为:" + str); }; MyDelegate1<string, int> md1 = (str) => { Console.WriteLine("有返回值的泛型委托"); Console.WriteLine("参数为:" + str); return 1 + 1; };
多播委托
多播委托也称为委托链,意思是委托的集合,使用+= 向集合中添加方法,使用-= 删除集合中的方法,在调用的时候统一调用
多播委托中的调用顺序不一定是添加的顺序
MyDelegate<string> md2 = new MyDelegate<string>(Method1); md2 += Method2; md2 += Method3; md2 += Method4; md2 += Method5; md2 -= Method3; md2("111");
多播委托的调用跟调用普通委托一样,使用实例名加括号。
以上的+=实际上在程序编译的时候会重新new一个委托,然后使用 Combine 将两个委托的调用列表连接在一起,返回一个新的委托列表
md2 = (MyDelegate<string>)Delegate.Combine(md2, new MyDelegate<string>(Method3));
Delegate.Combine 方法返回一个新的委托,但是类型是Delegate,Delegate是所有委托的父类,所以需要转换一下类型
多播委托的列表也可以被循环
foreach (Delegate @delegate in md2.GetInvocationList()) { ((MyDelegate<string>) @delegate)("123"); }
md2.GetInvocationList() 返回的是一个Delegate的数组,调用时候需要转换成MyDelegate系统委托系统委托
系统委托
有时候每次需要传递方法的时候都定义一个委托会有点麻烦,所以C#为我们定义了两个泛型委托 Action 和 Func
- Action 表示可以有参数但是没有返回值的委托
- Func 表示可以没有参数但是必须有返回值的委托
Action 使用时候有泛型和非泛型两种,非泛型为无参数无返回值的函数,有参数的方法在vs2017中最多是16个参数
Func 只有泛型的委托,Func只有一个参数时泛型为返回值的参数类型,有多个泛型参数时最后一个表示返回值的类型
// 无参数,无返回值 Action a = () => { }; // 多个参数,无返回值 Action<string, string> aciton = (s, s1) => { }; // 无参数,有返回值 Func<string> f = () => { return "fsa"; }; // 一个参数,有返回值 Func<string, int> func = s => { return 1; };