为何Visual Studio认为FirstOrDefaultAsync的返回值不可能为null
原因分析及解决方案
导致Visual Studio出现该判断偏差的核心原因和对应解决方法如下:
- 原因1:EF Core版本未适配可空引用类型注解
如果你使用的是EF Core 5及更低版本,这些版本并未对FirstOrDefaultAsync这类查询方法的返回值添加可空性注解。当项目开启可空引用类型(NRT)开关时,编译器会默认将引用类型返回值推断为「非空」,就会出现与实际逻辑不符的非空提示。
解决方法:升级EF Core到6.0及以上正式版,该版本开始官方已经对所有查询方法的可空性做了精准注解。 - 原因2:匿名类型的可空性推断规则限制
你当前查询投影的是匿名类型,C#编译器对匿名类型的可空性推断优先级要高于通用泛型方法的注解。如果你的代码中没有显式标注匿名类型变量可空,编译器会默认推断该变量不可能为null。
解决方法:C# 10及以上版本可以直接用var?显式声明变量可空:var? railcarInfo = await (from rt in DbContext.RailcarTrips where rt.WaybillRailcar.RailcarNumber == clm.RailcarNumber && rt.WaybillRailcar.Waybill.CreateDate <= clm.SightingDate orderby rt.WaybillRailcar.Waybill.CreateDate descending select new { RailcarTrip = rt, WaybillCreateDate = rt.WaybillRailcar.Waybill.CreateDate, IsLoaded = rt.WaybillRailcar.Weight > 0 }) .AsNoTracking() .FirstOrDefaultAsync(); - 原因3:静态流分析的前置判断影响
如果你在使用railcarInfo之前的代码路径中,已经存在该变量不为空的判断逻辑(比如if (railcarInfo == null) throw new ArgumentNullException(nameof(railcarInfo));),Visual Studio的静态流分析会标记后续代码路径中的该变量为非空,属于正常的分析结果。 - 原因4:项目可空引用类型配置异常
如果你的项目.csproj文件中可空配置为<Nullable>disable</Nullable>,所有引用类型都会被默认视为非空,自然不会出现空警告。如果你需要准确的空校验提示,建议将全局可空配置改为enable,再针对特殊场景单独调整可空标注。
内容的提问来源于stack exchange,提问作者Jonathan Wood
相关产品推荐
相关产品推荐

