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

C#可空场景下FirstOrDefault不同写法运行结果差异问题咨询

C# 空条件运算符链式调用差异原因解析

你遇到的差异本质是C# 空条件运算符?.的短路求值规则导致的,三种写法的运行逻辑完全不同,具体拆解如下:

IList<int> list = null;

var ans1 = list.FirstOrDefault(); //Fails

var temp = list?.ToList();
var ans2 = temp.FirstOrDefault(); //Fails

var ans3 = list?.ToList().FirstOrDefault(); //Passes

各写法执行逻辑说明

  • ans1报错原因:list本身是null,直接调用实例方法FirstOrDefault()属于对空对象执行实例成员访问,直接抛出NullReferenceException。
  • ans2报错原因:list?.ToList()的逻辑是如果list不为空则执行ToList(),如果为空则直接返回null,因此temp变量最终是null值。后续对temp调用FirstOrDefault()时,同样是空对象调用实例方法,自然会抛出空引用异常。这里的空条件运算符只保护了ToList()的调用,对后续FirstOrDefault()的调用没有任何保护作用。
    ans2的写法等价于:
    List<int> temp;
    if (list == null)
    {
        temp = null;
    }
    else
    {
        temp = list.ToList();
    }
    var ans2 = temp.FirstOrDefault(); // temp为null时直接触发空引用异常
    
  • ans3正常运行原因:空条件运算符?.支持链式调用的短路规则,只要?.左侧的对象为null,右侧整个链式调用的所有成员访问(包括这里的ToList()和FirstOrDefault())都不会执行,整个表达式直接返回对应类型的默认值:由于FirstOrDefault()返回值类型int,经过空条件运算符提升后会变为可空值类型int?,最终返回null,全程没有空对象访问操作,因此不会抛出异常。
    ans3的写法等价于:
    int? ans3;
    if (list == null)
    {
        ans3 = null;
    }
    else
    {
        ans3 = list.ToList().FirstOrDefault();
    }
    

ans2与ans3的核心差异

ans2和ans3的逻辑并不一致,核心区别就是空条件运算符的作用范围:ans2中?.仅作用于ToList()调用,后续的FirstOrDefault()是独立执行的,不受空判断保护;ans3中?.之后的整串链式调用都被空判断短路保护,只要前面为空后面所有逻辑都不会执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 04:36:03