如何避免C#代码中的NullReferenceException?排查空引用问题
需要解决代码中的NullReferenceException问题——当equipmentSpaceAssociations为可枚举空集合时,foreach循环会触发报错。
相关代码:
var spacesEquipmentAssociations = Spaces?.SelectMany(s => s.AirBalance.EquipmentExhaustAirflow.Equipment.Where(e => e.AirHandlerId != null)) ?? Enumerable.Empty<EquipmentSpaceAssociation>(); IncludeEquipmentAirflowsSum(exhaustEquipmentById, spacesEquipmentAssociations, true);
对应的方法实现:
private void IncludeEquipmentAirflowsSum<T>( IDictionary<Guid, T> exhaustEquipmentById, IEnumerable<EquipmentSpaceAssociation> equipmentSpaceAssociations, bool isSubtraction = false) where T : class, IMinMaxAirflow { _ = equipmentSpaceAssociations ?? throw new ArgumentNullException(nameof(equipmentSpaceAssociations)); double sign = isSubtraction ? -1D : 1D; foreach (var equipmentSpaceAssociation in equipmentSpaceAssociations) // 此处报错 { if (exhaustEquipmentById.TryGetValue(equipmentSpaceAssociation.EquipmentId, out var equipment)) { var multiplier = equipmentSpaceAssociation.Quantity * sign; EquipmentExhaustAirflow.MaxAirflow += equipment.MaxAirflow * equipmentSpaceAssociation.Diversity * multiplier; EquipmentExhaustAirflow.MinAirflow += equipment.MinAirflow * multiplier; } } }
尝试检查equipmentSpaceAssociations != null和equipmentSpaceAssociations?.Any(),但在equipmentSpaceAssociations?.Any()这一行也会出现相同的空引用错误。错误详情:
System.ArgumentNullException Message=Value cannot be null.
(Parameter 'source') Source=System.Linq StackTrace: at
System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument
argument) at System.Linq.Enumerable.Where[TSource](IEnumerable1 source, Func2 predicate) at
Domain.Shared.Models.ExhaustAirHandler.<>c__351.<ComputePropertiesMultiSpace>b__35_5(Space s) in C:\issue-dev\design-hub-dotnet\Domain\Shared\Models\AirHandlers\ExhaustAirHandler.cs:line 59 at System.Linq.Enumerable.SelectManySingleSelectorIterator2.MoveNext()
at
Domain.Shared.Models.ExhaustAirHandler.IncludeEquipmentAirflowsSum[T](IDictionary2 exhaustEquipmentById, IEnumerable1 equipmentSpaceAssociations,
Boolean isSubtraction) in
C:\issue-dev\design-hub-dotnet\Domain\Shared\Models\AirHandlers\ExhaustAirHandler.cs:line 82 at
Domain.Shared.Models.ExhaustAirHandler.ComputePropertiesMultiSpace[T](IDictionary`2
exhaustEquipmentById) in
C:\issue-dev\design-hub-dotnet\Domain\Shared\Models\AirHandlers\ExhaustAirHandler.cs:line 61
解决方案
从栈追踪可以看出,错误并非来自foreach循环本身,而是Linq查询的延迟执行阶段:SelectMany委托中,某个Space对象的s.AirBalance、s.AirBalance.EquipmentExhaustAirflow或s.AirBalance.EquipmentExhaustAirflow.Equipment为null,导致Where方法接收了null作为源集合,触发ArgumentNullException。
修复方法是在Linq查询中逐层添加空值检查,并用空集合兜底:
var spacesEquipmentAssociations = Spaces?.SelectMany(s => // 逐层检查空值,任意层级为null则返回空集合 s.AirBalance?.EquipmentExhaustAirflow?.Equipment?.Where(e => e.AirHandlerId != null) ?? Enumerable.Empty<EquipmentSpaceAssociation>()) ?? Enumerable.Empty<EquipmentSpaceAssociation>(); IncludeEquipmentAirflowsSum(exhaustEquipmentById, spacesEquipmentAssociations, true);
这样修改后,只要Space对象的任意关联属性为null,都会返回空集合,避免Where方法处理null源,从而解决枚举时的空引用错误。
内容的提问来源于stack exchange,提问作者kumar425

