专栏首页U3DC# 匿名回调方法在循环体中使用的注意事项

C# 匿名回调方法在循环体中使用的注意事项

今天在做AVG工具的选择分支功能时发现了一个问题,先把代码贴上来:

 1     private void SelectionParse(string value)
 2     {
 3         string[] ss = value.Split('|');
 4         List<GameObject> s_inss = new List<GameObject>();
 5 
 6         view.selection.SetActive(true);
 7 
 8         for (int i = 0; i < ss.Length; i++)
 9         {
10             string sc = ss[i].Split('@')[0];
11             string sid = ss[i].Split('@')[1];
12 
13             var ins = Instantiate(view.s_itemPrefab, view.selection.transform);
14 
15             s_inss.Add(ins);
16 
17             ins.GetComponentInChildren<Text>().text = sc;
18             int si = i;
19             ins.GetComponent<Button>().onClick.AddListener(() =>
20             {
21                 Debug.Log(i);
22                 Debug.Log(si);
23                 int id = int.Parse(sid);
24                 view.AddLogText("", sc);
25                 JumpToIDLine(id);
26                 foreach (var s_ins in s_inss)
27                 {
28                     s_ins.GetComponent<Button>().onClick.RemoveAllListeners();
29                     Destroy(s_ins);
30                 }
31                 view.selection.SetActive(false);
32             });
33         }
34     }

上面的代码中,i和si打印的结果是不同的:

如果我们直接在匿名回调方法中使用循环体中的增值变量i,得到的永远是固定的值,在上面的代码中也即是ss.Length的值。

然而很多时候我们需要的是当时的循环变量值,虽然在回调方法执行的时候这个循环体早已执行完成,但我们可以通过在循环体内回调方法外单独存储一个循环增量i的值,也即是上面的si,这样在后面的方法回调时便可以按照当时的增量i(也就是si)来取值。

总结就是:

si=循环体循环时增量i的值。

至于这个现象产生的原因,查阅后发现是因为C#后台为我们在回调方法执行之前就提前存储了该回调方法使用的外部变量。(感觉跟协程的挂起有点像)

也得益于这样的机制,在一些方法内部书写回调方法可以使一些复杂的逻辑极快的实现完成,避免了重复的传递参数和记录全局变量。

例如上面的短短几句话就实现了:

解析选项的文本内容,显示选项选单,根据选项数量创建对应个数的选项克隆,给克隆的对象添加文本内容和按钮监听,当这个按钮被按下时将选项对应的文本内容输出到Log中,执行跳转到选项对应id的文本位置,同时移除所有选项的按钮监听,销毁其余所有选项,并隐藏选项选单。一个完美的循环!

最重要的是这些只需要在一个方法中完成,这确实是令人兴奋的事。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Unity 基于Cinemachine计算透视摄像机在地图中的移动范围

    https://www.cnblogs.com/koshio0219/p/11820654.html

    汐夜koshio
  • Unity 随机地图房间通道生成

    https://www.cnblogs.com/koshio0219/p/12604383.html

    汐夜koshio
  • Unity NavMesh 动态烘焙绘制与随机取点

    最初的Unity导航系统很不完善,只能静态烘焙场景图的可行走区域,而且必须在本地保存场景的NavMesh数据,难以运行时动态计算;这使得鲜有开发者愿意再尝试Un...

    汐夜koshio
  • View.post的切身运用

      view.post方法指的是从正在操作其他线程的时候,将制定内容推到UI线程执行。因为布局的渲染只能在UI线程中执行。

    饮水思源为名
  • 微信小程序避坑指南

     详见官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/client-lib/cl...

    smy
  • 《金字塔原理》​必知的28条金句

    1.金字塔原理的四个基本原则:结论先行:每篇文章只有一个中心思想,并放在文章的最前面;以上统下:每一层次上的思想必须是对下一层次思想的总结概括;归类分组:每一组...

    用户1278550
  • 线性代数的本质课程笔记-特征向量/特征值

    视频地址:https://www.bilibili.com/video/av6540378/?spm_id_from=333.788.videocard.0

    石晓文
  • 矩阵相乘在GPU上的终极优化:深度解析Maxas汇编器工作原理

    在从事深度学习框架的实现工作时,了解到 Nervana 有一个称为 Maxas 的汇编代码生成器项目,可以生成性能超过 nVidia 官方版本的矩阵相乘的 GP...

    机器之心
  • 涨姿势!这才叫工业以太网

    工业以太网是基于IEEE802.3(Ethernet)的强大的区域和单元网络。利用工业以太网,SIMATICNET提供了一个无缝集成到新的多媒体世界的途径。继1...

    机器人网
  • js常用事件整理—兼容所有浏览器

    1.鼠标滚动事件。 说明:返回值 大于0向上滚动,小于0向下滚动。 兼容型:所有浏览器。 代码: /*********************** * 函数:...

    Java中文社群_老王

扫码关注云+社区

领取腾讯云代金券