【问题标题】:Why These two c# scripts give different results? [duplicate]为什么这两个 c# 脚本给出不同的结果? [复制]
【发布时间】:2020-10-19 06:56:31
【问题描述】:

我正在处理一个大按钮列表,并尝试使用快速方式为该列表中的每个按钮 AddListener()

第一种方法是

btn[0] = CHbutt[0].GetComponent<Button>(); btn[0].onClick.AddListener(delegate { CH(0); });
btn[1] = CHbutt[1].GetComponent<Button>(); btn[1].onClick.AddListener(delegate { CH(1); });
btn[2] = CHbutt[2].GetComponent<Button>(); btn[2].onClick.AddListener(delegate { CH(2); });
btn[3] = CHbutt[3].GetComponent<Button>(); btn[3].onClick.AddListener(delegate { CH(3); });

它工作得很好,AddListener()btn[] 中的所有按钮; 但是很多台词...

第二种方式

for (int i = 0; i < CHmatt.Count; i++)
{
    btn[i] = CHbutt[i].GetComponent<Button>(); btn[i].onClick.AddListener(delegate { CH(i); });
}

但是这个不起作用,这个AddListener()只到最后一个按钮btn[0]

我很好奇这两个脚本的区别。

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    这是一个捕获问题。改代码如下,避免捕获i

    for (int i = 0; i < CHmatt.Count; i++)
    {
        var ii = i;
        btn[i] = CHbutt[i].GetComponent<Button>(); 
        btn[i].onClick.AddListener(delegate { CH(ii); });
    }
    

    传入AddListener 函数的是delegate 方法;然而,由于您传入循环迭代变量i上下文被捕获i 被实际引用。随着循环的推进,i 的值会因所有捕获而发生变化,因此这种方法“不起作用”。

    通过引入i的本地副本(这里名称不重要,我称之为ii),它在每次循环迭代时超出范围,避免了i的捕获,并且实际ii 的值被传递给 delegate 方法(从技术上讲,被捕获,但它是每个循环迭代的 i 的副本,因此不会随着 i 的变化而变化。)

    【讨论】:

    • @CoolBots - 好多了。 :-)
    猜你喜欢
    • 1970-01-01
    • 2011-01-14
    • 2021-08-31
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多