匿名函数、Lambad表达式和闭包

一  匿名函数

1、 什么是匿名函

顾名思义,就是没有名字的函数, 本质还是函数,只不过没有名字。匿名函数的使用主要是配合委托和事件进行使用,脱离委托和事件是不能使用匿名函数的。

2、 基本语法

  delegate(参数列表)
 {

      函数体;

 };

3、 使用

不能单独使用,必须要有委托或者方法来装载匿名函数。实际就是一个委托类型的变量,可把它当作参数和返回值在函数之间穿梭。

using System;
using UnityEngine;
namespace 匿名函数学习 
{
    public class anonymous : MonoBehaviour
    {
        // Start is called before the first frame update
        void Start()
        {
            #region 3 使用
             // 1 无参无返回值
             // 申明匿名函数,并把它放到 无参无返回值的系统自带委托中
             // 这个地方只是申明匿名函数而已,还没有真正调用
             Action a= delegate ()
            {
                Debug.Log("匿名函数逻辑");
            };
            // 真正调用匿名函数
            a();

            // 2 有参数
            Action<int, string> a2 = delegate (int a, string b)
            {
                Debug.Log(a);
                Debug.Log(b);
            };
            a2(100, "chenzhuo");

            // 3 有返回值
            Func<string> f = delegate ()
            {
                return "123";
            };
            Debug.Log(f());
            // 4 一般情况会作为函数参数传递或者作为函数返回值
            // 参数传递
            Test t = new Test();
            Action ac = delegate ()
            {
                Debug.Log("随参数传入得匿名函数逻辑");
            };
            // 先用个委托把匿名函数存起来,在作为参数进行传递
            t.Dosomthing(50, ac);
            // 懒得存,一步到位,
            t.Dosomthing(100, delegate () 
            {
                Debug.Log("随参数传入得匿名函数逻辑");
            });
            // 作为函数返回值
            Action ac2= t.GetFun();
            // 把匿名函数返回出来在调用
            ac2();
            // 一步到位
            t.GetFun()();
            #endregion

            #region 4 匿名函数的缺点
            // 因为匿名函数没有名字 所以没有办法指定移除某一个匿名函数
            Action ac3 = delegate ()
            {
                Debug.Log("匿名函数一");
            };
            ac3 += delegate ()
            {
                Debug.Log("匿名函数二");
            };
            ac3();
            // 故此,不能通过-= 来移除对应的匿名函数
            // 此匿名函数,非彼匿名函数
            // 智能通过
            ac3 = null; // 来清除所有匿名函数
            #endregion
            Test test = new Test();
           // 一个函数传入一个整数,与之返回一个函数的传入参数相乘。
            Debug.Log(test.TestFun(10)(20)) ;
       }
    }

    class Test 
    {  
        public Action action= null;
        public Func<int,int> TestFun(int a)
        {
            return delegate (int b)
            {
                return a *b;
            };
        }
        public void Dosomthing(int a, Action fun)
        { 
            // 匿名函数被调用
            fun();
        }
        public Action GetFun() 
        {
            return delegate () { Debug.Log("函数内部返回一个匿名函数逻辑"); } ;
          //  return TestFun;
        }
       
    }

}

总结

  •  匿名函数 就是没有 名字的函数
  •  固定写法:delegate(参数列表){};
  • 主要在 委托传递和存储时,不用从新定义函数,可以直接使用匿名函数
  •  缺点:没有办法指定移除

二  lambad表达式

1、什么是lambad表达式

可以将lambad表达式理解为匿名函数的简写,它除了写法不同外,使用上和匿名函数一模一样都是和委托或者事件配合使用的。

2 、lambad 表达式语法

     (参数列表) =>
      {
           函数体;
      };

3 、lambad表达式使用

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;

public class Lambda : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
     
        #region 2 lambad 表达式语法
        // (参数列表) =>
        // {
        // 函数体
        // };
        #endregion
        #region 3 lambad 使用

        #endregion
        // 1 无参无返回值
        Action action = () => 
        {
            Debug.Log("lambad表达式");
        };
        action();
        // 2 有参数
        Action<string> action2 = (string str) => 
        { 
            Debug.Log("lambad表达式"+str); 
        };
        action2("1123");
        // 3 甚至参数类型都可以省略 参数类型和委托或者事件容器一致
        Action<int> action3 = (value) =>
        {
            Debug.Log("省略参数类型的写法"+value);
        };
        action3(200);
        // 4 有返回值
        Func<string, int> a4 = (value) =>
        {
            Debug.Log("有返回值的lambad表达式");
            return 1;
        };
        Debug.Log(a4("1123"));

    }
   
}

总结:

  • 匿名函数的特殊用法就是lambad表达式
  • 固定写法就是(参数列表)=>{ };
  • 参数列表可以直接省略参数类型
  • 主要在委托传递和存储时为了方便可以直接使用匿名函数或者lambad表达式
  • 缺点:无法指定移除

三  闭包

1、什么是闭包

  • 内层的函数可以引用包含在它外层的函数的变量
  • 即使外层函数的执行已经终止
  • 注意: 该变量提供的值并非变量创建的值,而是在父函数范围内的最终值(去代码中理解)

2、闭包的使用

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;

public class Lambda : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
       
        #region 闭包
        // 内层的函数可以引用包含在它外层的函数的变量
        // 即使外层函数的执行已经终止
        // 注意: 该变量提供的值并非变量创建的值,而是在父函数范围内的最终值

        Test test = new Test();
        test.DoSomething();

        #endregion
    }
    class Test 
    {
        // 声明一个事件
        public event Action action;
        public Test() 
        {
            int value = 100;
            // 这里就形成了闭包 可以在内函数中去引用外部函数的变量
            // 因为 当构造函数执行完毕时 其中声明的临时变量value 生命周期被改变了
            action = () =>
            {
                Debug.Log(value);   // 打印100
            };

            for (int i = 0; i < 10; i++)
            {
                action += ()=>
                {
                   // 注意: 该变量提供的值并非变量创建的值,而是在父函数范围内的最终值
                    Debug.Log(i);   // 打印的结果都是 10 
                };
            }

            for (int i = 0; i < 10; i++)
            {
                // 要解决这个问题,就在这个地方 声明一个临时变量 index,每次循环都会声明一个新的 index 临时变量
                int index = i;
                action += () =>
                {
                    Debug.Log(index);  // 打印的结果为 0,1,2,3,4。。。。9
                };
            }
        }
        public void DoSomething() 
        {
            action();
        }
    }
}

总结:

  • 内层的函数(主要指:委托和事件)可以引用包含在它外层的函数的变量
  • 注意,使用闭包时:临时变量的生命周期的变化。
  • 理解:该变量提供的值并非变量创建的值,而是在父函数范围内的最终值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值