在带有 select 表达式的 foreach 中使用 Null 合并运算符

Using Null coalescing operator in foreach with select expression

foreach (var item in Model.PublishedSong.RelatedSongs.Select((value, i) => new { value, i }) ?? Enumerable.Empty <dynamic>())
{

}

Related Songs 可能为 null 也可能不为 null,这里有什么方法可以使用 null 合并运算符吗?我仍然收到错误消息:

value cannot be null

像这样?

[编辑:删除了简化]

Model.PublishedSong
   .SelectMany(x=>
      (x.RelatedSongs??Enumerable.Empty<Song>())
         .Select((x,i) => new {Value = x, Index = i));

它计算为单个 Enumerable 而不是两个。

如果 RelatedSongs 为 null,对其调用 Select 将抛出 NullReferenceException,因为 null 合并运算符仅在 左侧计算方已解决。由于解析左侧会导致异常,因此对您没有任何好处。

如果您使用的是 C# 6.0,则可以使用 Null Propagation 运算符 - ?. - 仅当 RelatedSongs 不为空时调用 Select,并使用 Null否则合并运算符:

// This will return null if Relatedsongs is null, or call Select otherwise.
foreach (var item in Model.PublishedSong.RelatedSongs?.Select((value, i) => new { value, i })  
                             ?? Enumerable.Empty <dynamic>())
{
}

如果您使用的是 C# 5 或更早版本,则必须手动检查 null:

foreach (var item in Model.PublishedSong.RelatedSongs != null 
                             ? Model.PublishedSong.RelatedSongs.Select((value, i) => new { value, i }) 
                             : Enumerable.Empty <dynamic>())
{
}

我认为@juharr 的评论很好——如果在循环之前执行 null 检查,它可能更具可读性。但是,如果您真的想使用 null 合并运算符,这将起到作用:

foreach (var item in (Model.PublishedSong.RelatedSongs ?? Enumerable.Empty<TypeOfRelatedSong>()).Select((value, i) => new { value, i }))
{

}

您必须在尝试遍历 RelatedSongs 之前执行 null 检查。在您问题的示例中,您是在尝试迭代后执行此操作,因此出现异常。