除了自定义委托,VS提供了内置委托类型:Action/Func/Predicate等,目的是减少自定义委托的必要
1、学习Action委托 (动作) Action是一个没有参数,没有返回类型的委托类型
Action还有16个泛型重载:Action(T)/Action<T1,T2>/Action<T1,......T15,T16>,最多16个
目的:为了简化委托的使用
//原本应先定义委托,这里被Action代替 //public delegate void actAHandle(); class Demo{ Action actAHandle;//委托的声明 Public Demo(){ //委托注册 actAHandle+=Test1(); actAHandle+=Test2(); } public void Test1(){ Console.WriteLine("Test1"); } public void Test2(){ Console.WriteLine("Test2"); } //调用委托 public void DisPlayInfo(){ actAHandle(); } static void Main(string[] args){ Demo obj=new Demo(); obj.actAHandle(); } }
//学习Action泛型委托 class Demo(){ //声明泛型委托 Action<string> actHandle; public Demo(){ //注册泛型委托 actHandle+=Test1; actHandle+=Test2; } public void Test1(string str){ Console.WriteLine("Test1 参数="+str); } public void Test2(string str){ Console.WriteLine("Test2 参数="+str); } public void DisPlay(){ actHandle("你好"); } static void Main(string[] args){ Demo obj=new Demo(); obj.DisPlay(); } }
2、学习Func委托 (功能)
具有返回值的委托
规则:
1).必须有一个返回值。
2).Func泛型委托,在尖括号内的最后一个位返回类型,前面的均是参数
3).Func泛型委托,如果尖括号中只有一个参数,则表示返回类型
//学习Func委托 class Demo{ Func<string> funHandle; //无参 Func<string,int> funHandlerWithPara; //一个参数 public Demo(){ funHandle+=InvokeMethod; funHandlerWithPara+=InvokeMethod1; } public string InvokeMethod(){ Console.WriteLine("无参方法,有String类型返回数值"); return "你好"; } public int InvokeMethod1(string str){ Console.WriteLine("有参方法,返回类型是int类型"); return 0; } public void Display(){ //调用无参数的委托 funHandle.Invoke(); funHandlerWithPara("你好"); } static void Main(string[] args){ Demo obj=new Demo(); obj.Display(); } }
3、学习Predicate委托
具备布尔返回值的委托,
可以将Predicate委托看作是Func委托的特例,因为如下:
1)只能接受一个参数。
2)必须返回bool类型
3)功能上类似Func<T,bool>委托
//学习Predicate委托 class Demo{ Predicate<string> preHandler; public Demo(){ preHandler+=InvokeMethod; } private bool InvokeMethod(string str){ Console.WriteLine("返回bool数值的,有一个参数的方法,参数="+str); return true; } public void DisplayInfo(){ preHandler.Invoke("同学们"); } static void Main(string[] args){ Demo obj=new Demo(); obj.DisplayInfo(); } }
4、委托的优点
1)在算法不变的情况下,优化改进方法的执行效率
2)在算法不变的情况下,改变内部实现(可以随意改内部使用的方法名称)
3)方法中对于委托的调用,类似一直面向”接口“编程的策略,使得程序耦合性进一步降低。
5、委托的取值与清空
//得到委托列表 Delegate[] deleteArray=actDelete.GetInvocationList(); foreach(Delegate item in deleteArray){ item.DynamicInvoke(); } //清空委托列表 Delegate[] deleteArray=actDelete.GetInvocationList(); for(int i=0;i<deleteArray.Length;i++){ actDelete-=deleteArray[i] as Action; }
class Demo{ Action actHandler; public Demo(){ actHandler+=DeleMehtod1; actHandler+=DeleMehtod2; actHandler+=DeleMehtod3; } public void DeleMehtod1(){ Console.WriteLine("DeleMehtod1") } public void DeleMehtod2(){ Console.WriteLine("DeleMehtod2") } public void DeleMehtod3(){ Console.WriteLine("DeleMehtod3") } ///<summary> ///取得委托列表 ///</summary> public void DisplayInfo1(){ Console.WriteLine("取得委托列表"); Delegate[] delArray= actHandler.GetInvocationList(); foreach(Delegate item in delArray){ item.DynamicInvoke(); } } ///<summary> ///清空委托列表 ///</summary> public void DisplayInfo2(){ While(actHandler!=null){ actHandler -=this.actHandler; } Console.WriteLine("清空委托了"); //验证 if(actHandler!=null){ actHandler.Invoke(); }else{ Console.WriteLine("委托现在已经清空了"); } } ///<summary> ///清空委托列表更强大的算法 ///</summary> public void DisplayInfo3(){ Delegate[] delArray = actHandler.GetInvocationList(); for(int i=0;i<delArray.Length;i++){ actHandler-= delArray[i] as Action; } //测试 if(actHandler!=null){ actHandler.Invoke(); }else{ Console.WriteLine("委托现在已经清空了"); } } static void Main(string[] args){ Demo obj=new Demo(); //obj.DisplayInfo1(); //obj,DisPlayInfo2(); obj.DisPlayInfo3(); } }
6、匿名方法
”匿名方法“就是没有名字的方法,由于没有方法名称,所以只能赋值给一个委托来进行调用,其作用是减少代码量,减少复杂性,且这个方法不需要在别处调用。本质上还是方法,使用委托的地方可以应用。
//学习匿名委托 class Demo{ //使用匿名方法 public void Test(){ Func<int,int,int> funAddingMethodHandler=delegate(int num1,int num2){ retrun num1+num2; };//这个地方一定要加分号 //调用测试 int result=funAddingMethodHandler.Invoke(20,30); } static void Main(string[] args){ Demo obj=new Demo(); obj.Test(); } }
7、Lambda表达式
Lambda表达式的本质就是匿名方法的简写形式。
减少了delegate关键字,以及参数的类型
当方法体只有一句话的时候,可以不写大括号,不加return
当方法的参数只有一个的时候,可以不写括号
还可以访问表达式之外的变量(不推荐)
/*学习Lambda表达式 专有符号: => 对于”匿名方法“的简化步骤 1:去掉delegate关键字 2:去掉方法的参数的类型定义 3:方法体只有一句话,去掉大括号,不加return 4:方法参数只有一个的时候,去掉括号 */ class Demo{ public void Test(){ //匿名方法 Func<int,int,int> funAddingMethodHandler=delegate(int num1,int num2){ retrun num1+num2; }; //Lambda Func<int,int,int> funAddingMethodHandler1=(num1,num2)=>num1+num2; //测试 Console.WriteLine(funAddingMethodHandler1(10,20)); } static void Main(string[] args){ Demo obj=new Demo(); obj.Test(); } }
8、委托与事件的区别
委托可以声明一个局部变量,事件只能作为一个类的成员(即字段)来声明,所以可以认为事件就是委托的一个特殊实例,即受限制的委托。
委托可以作为方法的参数,事件不可以。