• Unity C#笔记 委托/事件/Action/Func/Lambda表达式



    C#里的委托相当于C#的函数接口对象(C语言可称为函数指针,C++可称为函数对象),是C#的一个比较重要的特性。

    而观察者模式是一种常见的设计模式,在C#里往往使用委托等相关语法搭配来实现观察者模式。

    因此很需要搞懂 delegate(委托),event(事件),Action/Func的语法及区别。
    此外观察者模式的原理很易懂,不作多讲,本文纯粹用于记录C#委托/时间/Lambda表达式语法。

    delegate(委托)

    //声明没有参数,没有返回值的委托类型XXXX
    public delegate void XXXX();
    

    声明一个委托类型(类似typedef XXXX C++/C的函数类型)

    注:不是产生一个对象。

    然后利用声明出来的委托类型,我们可以利用它的对象,赋予其对应类型的函数。
    从而实现出类似调用函数指针的效果。

    //委托类型XXXX的对象
    public XXXX delegateObj1;
    
    public void func1(){}
    public void func2(){}
    public void func3(int a){}
    
    //可将某个同样类型的函数赋给该对象
    delegateObj1 = func1;
    
    //调用委托对象等同于调用它代表的函数
    delegateObj1();//等价于func1();
    
    delegateObj1 = func2;
    delegateObj1();//等价于func2();
    
    delegateObj1 = func3;//类型不匹配,语法错误
    

    event(事件)

    单纯用委托的话只能一对一调用(一次调用,一个函数触发)。

    而通过利用事件机制,我们可以实现一对多的调用(一次调用,多个相关事件(函数)触发)。

    而且它添加/移除委托对象(相当于观察者模式里的观察者)的操作十分方便,使用+=或-=即可。

    //先声明一个委托类型
    public delegate void XXXX();
    //委托事件对象
    public event XXXX EventObj1;//此处比一般委托多了个event
    
    EventObj1 += func1; //添加
    EventObj1 += func2; //添加
    
    EventObj1(); //调用func1(),func2()
    
    EventObj1 -= func1; //移除
    EventObj1(); //调用func2()
    

    Action/Func

    Action/Func主要是为了简化委托(delegate)语法,它们本质都是委托。

    //无返还值,不带参数的委托对象
    public delegate void XXXX();
    public XXXX obj1;
    

    在上面我们看到委托语法,必须为委托类型命名(声明委托),才能使用该委托类型。

    但是使用Action/Func可以无需声明委托类型的语句,直接利用Action<...>/Func<...>来用自己想要的委托类型。

    Action和Func的源码底层实际也是delegate的封装

    • Action<...>用于无返还值的委托类型
    • Func<...,T>用于有返回值的委托类型,最后一个类型参数 T 代表返还值类型。
    //无返还值,不带参数的委托对象
    public Action obj3;
    //无返还值,带int参数的委托对象
    public Action<int> obj4;
    
    //double返还值,无参数的委托对象
    public Func<double> obj5;
    //int返还值,带string,double参数的委托对象
    public Func<string,double,int> obj6;
    
    //将Action应用至事件
    public event Action<int> EventObj1;
    
    EventObj1 += obj4;
    EventObj1 += func1;
    EventObj1 += func2;
    EventObj1();//调用obj4(),func1(),func2()
    

    Lambda表达式

    Lambda表达式是用于简便快速写简单函数的语法,而且这些函数往往要用于委托对象。

    Lambda表达式基本形式:

    (参数...) => { 函数内容... }
    

    参数在它的类型可自动推导的情况下,才可以省略参数类型。如果谨慎起见,可以不省略,从而避免隐式类型转换。

    Action obj1;
    obj1 = () => { Debug.Log("FGNB"); };
    
    Action<int> obj2;
    obj2 = (int x) => { Debug.Log(x); };
    obj2 = (x) => { Debug.Log(x+233); };//也可以省略参数类型
    
    Func<int,int> obj3 = (int x) => { return x; };
    
    

    结论

    • 为了简化语法,可使用Action/Func而不是直接使用delegate,除非你想强调特殊的委托类型。
    • 实现观察者模式,可以使用event和委托(Action/Func/delegate)搭配。更加完善的做法则是再搭配Dictionary,通过Key找到想要的委托事件对象列表,然后可以添加/移除/通知该对象的观察者。
    • Lambda表达式适用于快速编写简短的函数,复杂的函数应该做成类方法方便调试。
  • 相关阅读:
    判断单链表中是否有环,找到环的入口节点的理论证明
    交叉熵代价函数(作用及公式推导)
    C#调用C++、Opencv的Dll
    腾讯机器学习一面面经
    C#调用C++类库的几种方式
    2017年腾讯基础研究笔试感受
    关于开源库或者SDK的文档问题
    卷积神经网络Lenet-5实现
    NULL、0、nullptr 区别分析
    C++中,new/delete和malloc/free的区别
  • 原文地址:https://www.cnblogs.com/KillerAery/p/10509940.html
Copyright © 2020-2023  润新知