C#之深入学习委托与事件

除了自定义委托,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、委托与事件的区别

委托可以声明一个局部变量,事件只能作为一个类的成员(即字段)来声明,所以可以认为事件就是委托的一个特殊实例,即受限制的委托。

委托可以作为方法的参数,事件不可以。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱卷的小Zang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值