闭包问题C# Lua

闭包问题汇总(之前有个大佬时不时问几个问题,现在来总结下经验)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ToggleTest : MonoBehaviour
{
    
    
    public Toggle[] toggles;
    private void Start() {
    
    
        for (int i = 0; i < toggles.Length; i++)
        {
    
    
            toggles[i].onValueChanged.AddListener((isOn)=>OnToggleChanged(isOn,i));
        }
    }
    private void OnToggleChanged(bool isOn,int index){
    
    
        Debug.Log($"index==>{
      
      index}..State===>{
      
      isOn}");
    }
}

看到这里可以先猜猜选择Toggle打印结果会是多少?Toggle单选按钮有三个。

可以看到Index始终为3。。。

为什么结果会是3呢?这里就会提到闭包这个概念:内层的函数可以引用包含在它外层的函数的变量,即使外层函数的执行已经终止。但该变量提供的值并非变量创建时的值,而是在父函数范围内的最终值。正常来讲For循环执行完毕的时候i变量的内存会随着For循环结束而结束生命。但是由于匿名函数引用了i,导致i不能随For循环结束而结束。所以这个时候i=3.当我们执行点击的时候index=3.这里问题就找到了,那么应该如何解决呢?

解决方案

在这里插入图片描述

这样就解决了。想要弄清楚解决的思路,还是得从内存谈起。上一张没有int t = i的代码中。i有几个内存地址呢?可以看出来i只有一个内存地址。而当前图中t有几个内存地址呢?很明显有三个,每次For循环进来都会声明一个t的内存地址。并且t的值随着For循环结束都是不同的。分别是0,1,2。所以问题到这里就可以完全理解了。

在这里插入图片描述

Lua中的闭包

function newCounter()
    local i = 0
    return function()
        i = i + 1
        return i
    end
end
c1 = newCounter()
print(c1())
print(c1())

结果应该是1,2.i本来应该在NewCounter调用结束时候就随之释放内存。但是由于内部函数引用,所以内存继续存在,第一次执行完c1()i = 0+1 = 1;第二次执行c1()完i就应该为i = 1+1 =2;

function newCounter()
    local i = 0
    return function()
        i = i + 1
        return i
    end
end
c1 = newCounter()
print(c1())
c1 = nil
c2 = newCounter()
print(c2())

结果应该是1,1.因为第一次执行完c1()i = i + 1 = 0 + 1 = 1;但是接下来c1=nil等于释放了内存。c2 = newCounter() 执行c2()时候这个时候i为0.所以c2()结果为i = i + 1 = 0 + 1 = 1;所以最终结果为1,1.

猜你喜欢

转载自blog.csdn.net/qq_39691716/article/details/125260876