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

在LINQ数组搜索中正确使用?.空条件操作符的疑问与解法

空条件操作符在foreach中失效的原因及优化方案

为什么你的?.写法无法正常工作?

问题出在两个核心点:

  • 空条件操作符的作用范围有限:Servers?.Find(...)仅在Servers为null时返回null,但后续的.Online没有加?.——如果Find返回null,直接访问.Online会触发空引用异常。就算给Online也加上?.,比如ServersHolder.Servers?.Find(f => f.ID == 9999)?.Online?.FindAll(...),最终如果某一步返回null,foreach尝试遍历null时还是会报错,因为foreach要求遍历对象必须是合法的枚举类型,不能为null。
  • 链式调用的空值不自动传递:?.只会对当前的成员访问生效,不会自动作用于整个调用链的后续环节。

先判断Exists的写法存在的问题

这种写法能避免空引用,但有明显缺陷:

  • 重复遍历集合:Exists和Find会先后遍历Servers集合查找目标服务器,造成不必要的性能损耗。
  • 线程安全隐患:如果在Exists检查和Find调用之间,Servers集合被修改(比如目标服务器被移除),Find会返回null,仍会触发空引用异常。

更优的解决方案

一次性获取目标服务器,逐层处理空值,并用空合并运算符确保foreach有合法的枚举对象:

var targetServer = ServersHolder.Servers?.Find(f => f.ID == 9999);
// 用?? Enumerable.Empty<YourUserType>()确保即使前面返回null,也有可遍历的空集合
var targetUsers = targetServer?.Online?.FindAll(g => g.LoginPhase == 3) ?? Enumerable.Empty<YourUserType>();

foreach (var user in targetUsers)
{
    await trySendPacket(9999, user.GUID.ToString(), OpCode.SentNotifyUserLeft, "", 2);
}

如果使用C# 8.0及以上版本,还可以用模式匹配简化代码,可读性更高:

// 用模式匹配一次性验证非空,避免逐层判断
if (ServersHolder.Servers?.Find(f => f.ID == 9999) is { } targetServer
    && targetServer.Online?.FindAll(g => g.LoginPhase == 3) is { } targetUsers)
{
    foreach (var user in targetUsers)
    {
        await trySendPacket(9999, user.GUID.ToString(), OpCode.SentNotifyUserLeft, "", 2);
    }
}

这种写法既避免了重复遍历,又能安全处理所有空值场景,代码逻辑更严谨。

内容的提问来源于stack exchange,提问作者Josh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 12:33:24