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
相关产品推荐
相关产品推荐

