C# 在foreach中添加侦听器

C# 在foreach中添加侦听器,c#,unity3d,foreach,lambda,C#,Unity3d,Foreach,Lambda,foreach语句中的lambda突然出现问题: IEnumerator RefreshNextFrame( Part Current ) { yield return null; if( Current.Nodes == null ) yield break; Current.Nodes.ForEach( n => Debug.Log( n.name ) );//outputs node0, node1 for( int i = 0; i

foreach语句中的lambda突然出现问题:

IEnumerator RefreshNextFrame( Part Current )
{
    yield return null;
    if( Current.Nodes == null )
        yield break;
    Current.Nodes.ForEach( n => Debug.Log( n.name ) );//outputs node0, node1
    for( int i = 0; i < Current.Nodes.Count; i++ )
    {
        Node node = Current.Nodes[i];
        Button button = Instantiate( Resources.Load<GameObject>( "Prefabs/Button" ) ).GetComponent<Button>();
        button.transform.SetParent( content );
        button.GetComponentInChildren<Text>().text = node.name;
        button.onClick.AddListener( delegate
        {
            Debug.Log( button.GetComponentInChildren<Text>().text );
        } );
    }
}
IEnumerator刷新下一帧(部分当前)
{
收益返回空;
if(Current.Nodes==null)
屈服断裂;
Current.Nodes.ForEach(n=>Debug.Log(n.name));//输出节点0,节点1
对于(int i=0;i

点击按钮总是输出
节点1

由于此代码,所有内容都在例程中。以下是答案

只需在每次迭代中分配一个新的局部变量,并将该局部变量用于AddListener

编辑 快速示例:

MyFunction将始终接收100作为i的值:

for (int i=0; i<100; i++) {
    button.onClick.AddListener(() => MyFunction(i));
}
for(int i=0;i MyFunction(i));
}
但如果您这样做,它将正常工作:

for (int i=0; i<100; i++) {
    int iLocal = i;
    button.onClick.AddListener(() => MyFunction(iLocal));
}
for(int i=0;i MyFunction(iLocal));
}

尝试将行设置为Current.Nodes.ForEach(n=>Debug.Log(n.name));输入lambda表达式,查看两个节点是否仍具有预期的名称。也许您稍后会在代码中的其他地方覆盖它们,而不知道。否。如我所料命名。此代码在couroutine中。这有意义吗?试着按下按钮。在GetComponentChildren()之前。lambda表达式中的文本。也许你甚至不是从按钮中获取子对象,而是从这个代码所在的对象中获取。因此,这行代码如下所示:Debug.Log(button.getComponentChildren().text);是的,这是不对的,但现在它是所有按钮上的node1输出。同样的问题。很有趣,所以lambda中的lambda不会复制上下文。:)我们已经讨论过了,它不起作用,因为他的代码是在Unity couroutine中执行的,而Unity couroutine本身就是一个保存了上下文的lambda表达式。在其中创建lambda表达式不会保存上下文,这就是它不起作用的原因。