美文网首页
Unity_新手必懂知识点|匿名函数lambda表达式等函数嵌套

Unity_新手必懂知识点|匿名函数lambda表达式等函数嵌套

作者: riki_tree | 来源:发表于2019-04-29 11:41 被阅读0次

    翻车了!!!一个小例子带你了解闭包。

    事故现场:

    场景:6个button,上方1个text。点击button,text会显示button上的数字。


    closure1.gif

    代码如下:

        //在unity里面赋值
        public List<Button> buttons = new List<Button>();
        public Text text;
        void Start () {
            AddFun();
        }
        //给6个button添加点击事件
        void AddFun()
        {
            for (int i = 0; i < buttons.Count; i++)
            {
                buttons[i].onClick.AddListener(() => Fun(i + 1));
            }
        }
      //点击事件:输出形参的值
        void Fun(int i)
        {
            text.text = i.ToString();
            print(i);
        }
    

    for循环button添加onclick函数导致点击所有的button显示同样的莫名数字7。

    事故原因:

    闭包。标题那么长跟闭包有什么关系?因为上述问题会引起闭包。为什么标题中不直接写出关键字闭包?因为叫的出闭包的人基本上都会避免这个问题,这篇文章主要针对新人,那些没听过闭包的人。

    事故分析:

    1、什么是闭包?我也不知道哈,非科班,定义百度一下吧。

    2、怎么会产生闭包?内部函数使用了外部函数的局部变量。内部函数:是我对匿名函数,lambda表达式等函数嵌套情况的称呼。如上述例子:外部函数Addfun,内部函数是lambda表达式,i是外部函数for循环中的局部变量,内部函数lambda表达式使用了i这个局部变量。

    3、闭包会导致什么的结果?闭包会延长所用外部函数局部变量的生命周期,或者说是局部变量变成了全局变量。

    内存分析:

    memory1.png

    通俗的讲就是局部变量i从没被释放,一直存在内存中,随着i++,值增到了6,所有button的点击函数都是传进的i+1,也就是7,为实参,所以fun函数打印的数字为7

    处理办法:

    重新申请内存。代码如下:

        public List<Button> buttons = new List<Button>();
        public Text text;
        void Start () {
            AddFun();
        }
        
        void AddFun()
        {
            for (int i = 0; i < buttons.Count; i++)
            {
                //重新申请的内存
                int index = i;
                buttons[i].onClick.AddListener(() => Fun(index + 1));
            }
        }
        void Fun(int i)
        {
            text.text = i.ToString();
            print(i);
        }
    

    内存分析:

    memory2.png

    通过初始化重新申请了6块内存,每块内存保存了不同的index值(index值是由i赋值而来)。虽然index变量的生命周期也被延长,但是不同的button的点击函数访问的传进参数的内存不同,因此fun函数打印的数字也就不同。

    事件解决:

    closure2.gif

    拓展:

    其实闭包在脚本语言中非常常见,也非常有用。以lua为例,代码如下:

    function OutSideFun()
    
        local i=0
        local function InsideFun()
            i=i+1
            print(i)
        end
        
        return InsideFun
    end
    
    
    local fun=OutSideFun()
    
    fun()
    fun()
    fun()
    

    那么自己可以试试输出值是多少,分析一下为什么是这样。

    小结

    知识点:闭包,会导致外部函数的局部变量生命周期延长。

    相关文章

      网友评论

          本文标题:Unity_新手必懂知识点|匿名函数lambda表达式等函数嵌套

          本文链接:https://www.haomeiwen.com/subject/ggtynqtx.html