为何List.IndexOf查找lambda表达式形式的Action时返回-1?
为什么List.IndexOf查找lambda表达式返回-1?
这个问题的核心在于委托的相等性判断规则,以及lambda表达式的创建机制,咱们一步步拆解:
1. Lambda表达式每次创建都是新的委托实例
当你写() => DisplayTextBlock(...)这样的lambda时,编译器会为每次这样的写法生成一个全新的匿名方法委托实例——哪怕代码逻辑完全一模一样,它们也是内存中不同的对象。List<T>.IndexOf默认用引用相等性(针对引用类型)查找元素,所以两个看起来一样的lambda,本质是不同的对象,自然找不到。
2. 你的代码里的双重问题
再看你的具体代码:
- 你添加到列表里的是
() => DisplayTextBlock(block3 = new TextBlock("3.some text here")),这个lambda包含block3 = new TextBlock(...)的赋值操作; - 而你用来查找的是
() => DisplayTextBlock(block3),这不仅是全新的委托实例,连执行逻辑都和列表里的那个不一样(一个是先创建赋值再调用,一个是直接调用已存在的变量)。
哪怕你把查找的lambda改成和添加时完全相同的代码,结果还是返回-1,因为它依然是新的委托实例。
解决办法
办法一:存储委托实例到变量再使用
如果你需要后续能找到这个Action,先把它赋值给一个变量,再添加到列表,查找时直接用这个变量:
// 先定义变量存储委托 Action showBlock3 = () => DisplayTextBlock(block3 = new TextBlock("3.some text here")); // 添加变量到列表 textDisplay.Add(showBlock3); // 查找时直接用这个变量 myActiveTextIndex = textDisplay.IndexOf(showBlock3);
这样因为是同一个委托实例,IndexOf就能正确找到对应的索引。
办法二:自定义匹配逻辑(如果无法提前存储变量)
如果没办法提前保存委托实例,你可以遍历列表,通过自定义条件匹配。比如给每个TextBlock加个标识属性,然后在遍历的时候检查:
// 假设TextBlock有个Id属性用来标识 int targetId = 3; myActiveTextIndex = textDisplay.FindIndex(action => { // 这里需要根据实际场景,获取当前Action对应的TextBlock标识 // 比如创建lambda时捕获对应的ID: // 创建时:int id = 3; textDisplay.Add(() => DisplayTextBlock(block3 = new TextBlock(id, "3.some text here"))); // 核心是找到能唯一识别这个Action的特征,进行匹配 });
内容的提问来源于stack exchange,提问作者mrK
相关产品推荐
相关产品推荐

