在含null元素的List中使用Predicate<T>与Exists遇空引用异常的解决
问题:处理含null元素的列表查找时触发NullReferenceException
我尝试用listx.FindIndex(SomePredicate<T>)查找列表元素索引,出现以下错误:
NullReferenceException: Object reference not set to an instance of an object
之后又试了listx.Exists(SomePredicate<T>),我的列表长度固定且包含null值(用于Unity背包系统)。简化代码如下:
public class Item { public int id; public string itemname; // 构造函数等... } // 在另一个类中: List<Item> inventory = new List<Item>(); for (int i = 0; i < 4; i++) { inventory.Add(null); } inventory[0] = new Item(0, "YellowBox"); inventory[1] = new Item(1, "RedBox"); // inventory[2]、inventory[3] 保持为null // 正常运行,因为在遇到null前找到匹配项 string itemname = "RedBox"; inventory.Exists(item => item.itemname == itemname); // 运行失败,推测是遍历到inventory[2]的null时,无法访问itemname string itemname = "BlueBox"; inventory.Exists(item => item.itemname == itemname);
请问如何先检查null,或者有没有Exists的替代方法?
撰写问题时我想到一个思路(因为需要索引,仅跳过null不够),写了如下方法:
public int FindItemIndex(string itemname) { int index = -1; for (int i = 0; i < 4; i++) { if (inventory[i] == null) { continue; } if (inventory[i].itemname == itemname) { return i; } } return index; }
使用方式:
if (FindItemIndex(itemname) < 0) { // 未找到元素的处理代码 } else { // 使用索引的代码,例如移除inventory[index]处的元素 }
另外,inventory.Where(Item => Item != null)是否可用?希望得到建议。
解决方案与建议
1. 直接在Lambda表达式中增加null判断
这是最简洁的方式,不用自己写循环,直接利用List内置方法:
- 对于
Exists,修改为:inventory.Exists(item => item != null && item.itemname == itemname); - 对于
FindIndex,同样增加null判断:
这样遍历到null元素时会直接跳过,不会触发空引用异常,完全适配你的场景。int index = inventory.FindIndex(item => item != null && item.itemname == itemname); // 未找到时返回-1,和自定义方法逻辑一致
2. 自定义FindItemIndex方法是可行的
你自己实现的方法逻辑清晰,适合需要自定义遍历规则的场景(比如之后要增加更多过滤条件)。如果习惯这种显式循环的写法,完全可以继续使用,性能上和内置方法差异极小。
3. 关于inventory.Where(Item => Item != null)的用法
这个Linq方法会过滤掉列表中的null元素,返回一个IEnumerable<Item>,但要注意:
- 若仅需判断元素是否存在,可用Linq的
Any方法,效果和Exists类似:bool exists = inventory.Any(item => item != null && item.itemname == itemname); - 若要获取匹配的元素,可用
FirstOrDefault:Item foundItem = inventory.FirstOrDefault(item => item != null && item.itemname == itemname); - 但如果需要原列表的索引,单纯用
Where不行——过滤后的序列索引和原列表不对应,这种情况还是用FindIndex或自定义循环更直接。
内容的提问来源于stack exchange,提问作者Elight
相关产品推荐
相关产品推荐

