在 foreach 中使用空合并运算符和选择表达式

本文关键字:运算符 选择 表达式 合并 foreach | 更新日期: 2023-09-27 18:33:39

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

相关歌曲可能是也可能不是空的,有什么方法可以在这里使用空合并运算符吗?我仍然收到错误消息:

值不能为空

在 foreach 中使用空合并运算符和选择表达式

如果 RelatedSongs 为 null,则对其调用 Select 将引发 NullReferenceException,因为只有在解析左侧才会计算 null 合并运算符。而且由于解决左侧会导致异常,因此对您没有任何好处。

如果使用的是 C# 6.0,则可以使用 Null 传播运算符 - ?. - 仅在 RelatedSongs 不为 null 时调用 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>())
{
}

像这样?

[编辑:删除了简化]

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

它的计算结果为单个可枚举,而不是两个。

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

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

在尝试迭代RelatedSongs之前,您必须执行空检查。 在您的问题示例中,您在尝试迭代后执行此操作,因此例外。