Enumerable.Last() 抛出 InvalidOperationException 异常 "Sequence contains no matching element"

3
在一个预排序的List<int>中,我将要查找满足条件的最后一个元素,例如int lastScore = list.Last(x => x < 100)。如果列表中没有任何元素满足此条件,则会抛出一个InvalidOperationException异常,其中包含错误消息:Sequence contains no matching element。这种情况也会发生在使用list.First(...)时。
我甚至尝试将lastScore设置为可空类型,但没有成功。
难道捕获异常并手动将lastScore赋值为null是唯一的解决办法吗?

欢迎来到SO!话虽如此,我对你的问题感到困惑。List<int>不能是list的类型,因为当然int没有Score属性。请澄清一下。 - J0e3gan
非常抱歉!我本意是写 list.Last(x => x < 100)。感谢您指出来。我也已经编辑了问题。 - Vivekanand P V
2个回答

4

如果您正在使用引用类型,请使用FirstOrDefaultLastOrDefault来获取null,以便在没有匹配项的情况下返回值。对于值类型,这些方法将返回默认值


1
在这种情况下(IEnumerable<int>),它将返回0,而不是null。如果0是有效值,则实际上会出现问题。一种解决方案是首先将序列转换为IEnumerable<int?>,尽管在这种情况下我可能只是处理异常。 - user2864740
真的。那么,解决方案是什么? - Vivekanand P V
刚刚发现FirstOrDefaultLastOrDefault对于值类型会返回默认值(例如int的默认值为0)。而对于IEnumerable<T>中的引用类型T,它们会返回null - Vivekanand P V

0

在使用的最接近点,我可能只是捕获异常。

这是因为对于一个IEnumerable<int>上的LastOrDefault/FirstOrDefault方法将返回0(int的默认值),这个可能是一个"有效"值-这取决于实际的上下文和定义的规则。虽然将序列转换为IEnumerable<int?>可以让前面的方法返回null,但这似乎比其价值更多的工作。

如果需要在后续使用中使用lastScore,请考虑:

int? lastScore;  /* Using a Nullable<int> to be able to detect "not found" */
try {
   lastScore = list.Last(x => x < 100);  /* int -> int? OK */
} catch (InvalidOperationException) {
   lastScore = null; /* If 0 see LastOrDefault as suggested;
                        otherwise react appropriately with a sentinel/flag/etc */
}
if (lastScore.HasValue) {
   /* Found value meeting conditions */
}

或者如果能够在未找到时放弃该情况,请考虑:

try {
   var lastScore = list.Last(x => x < 100);
   /* Do something small/immediate that won't throw
      an InvalidOperationException, or wrap it in it's own catch */
   return lastScore * bonus;
} catch (InvalidOperationException) {
   /* Do something else entirely, lastScore is never available */
   return -1;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接