关于Unity c#里面闭包的问题

版权声明:@转载请注明原地址 https://blog.csdn.net/qq_33413868/article/details/79981104

今天写造梦西游 使用for循环给物体添加事件的时候遇到了这个问题

for (int i = 0; i < List_Levels.Count; i++)
        {
            EventTriggerListener.Get(List_Levels[i]).onEnter = () => { OnLevelMouseEnter(List_Levels[i]); };
            EventTriggerListener.Get(List_Levels[i]).onExit = () => { OnLevelMouseExit(List_Levels[i]); };
            EventTriggerListener.Get(List_Levels[i]).onClick = () => { OnLevelMouseClick(List_Levels[i]); };
        }

这样传入lambda里面的i值全都是一样的值,而不是预想的0,1,2..maxCount

后来经过一番查询发现是闭包陷阱问题,可以这样解决

for (int i = 0; i < List_Levels.Count; i++)
        {
            int j = i;
            EventTriggerListener.Get(List_Levels[j]).onEnter = () => { OnLevelMouseEnter(List_Levels[j]); };
            EventTriggerListener.Get(List_Levels[j]).onExit = () => { OnLevelMouseExit(List_Levels[j]); };
            EventTriggerListener.Get(List_Levels[j]).onClick = () => { OnLevelMouseClick(List_Levels[j]); };
        }

在里面新建一个变量,将i的值赋给j  下面的参数使用j  就可以解决

具体内部的原因由于能力有限解释不清楚,请大家自行百度...

------------------在经过了一番调查之后发现了闭包的秘密------------------------

https://blog.csdn.net/qq_33413868/article/details/81460893 38条为此秘密的基础

因为在Main方法的内部又生成了一个B方法,且使用的参数是Main方法的内部变量,B方法不知何时调用,因此延长了Main方法内部变量 i 的生命周期,当for循环执行完,i值变为5不符合条件会跳出来,此时因为类内部所有要延长的Main方法里面的内部变量都是一个 i ,但是 i 已经变成了5,所以调用匿名方法B输出的 i 全都是5.

当我们每一次循环都新建一个变量的时候,此匿名方法B延长的是一个新建的 temp 变量的生命周期,而且每一次的temp 都是新建的,所以不存在前面的匿名方法B调用的时候里面存储的值已经改变一说

 

阅读更多

没有更多推荐了,返回首页