You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在含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判断:
    int index = inventory.FindIndex(item => item != null && item.itemname == itemname);
    // 未找到时返回-1,和自定义方法逻辑一致
    
    这样遍历到null元素时会直接跳过,不会触发空引用异常,完全适配你的场景。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:11:06