所以我经常遇到这种情况……Do.Something(…)返回一个空集合,如下所示:
int[] returnArray = Do.Something(...);
然后,我尝试像这样使用这个集合:
foreach (int i in returnArray)
{
// do some more stuff
}
我只是好奇,为什么foreach循环不能操作一个空集合?在我看来,零次迭代将被一个空集合执行是合乎逻辑的……相反,它抛出一个NullReferenceException。有人知道为什么吗?
这很烦人,因为我使用的api不清楚它们返回什么,所以我最终到处都是if (someCollection != null)。
我认为这里提供的答案对为什么抛出异常的解释非常清楚。我只是想补充一下我通常处理这些系列的方式。因为,有些时候,我不止一次地使用集合,并且每次都必须测试是否为空。为了避免这种情况,我采取了以下措施:
var returnArray = DoSomething() ?? Enumerable.Empty<int>();
foreach (int i in returnArray)
{
// do some more stuff
}
通过这种方式,我们可以尽可能多地使用集合,而不用担心异常,也不会用过多的条件语句污染代码。
使用空检查操作符?。也是一个很好的方法。但是,在数组的情况下(就像问题中的例子),它应该在下面转换为List:
int[] returnArray = DoSomething();
returnArray?.ToList().ForEach((i) =>
{
// do some more stuff
});
空集合和对集合的空引用之间有很大区别。
当你在内部使用foreach时,这会调用IEnumerable的GetEnumerator()方法。当引用为空时,将引发此异常。
但是,使用空IEnumerable或IEnumerable< t>是完全有效的。在这种情况下,foreach将不会“迭代”任何东西(因为集合是空的),但它也不会抛出,因为这是一个完全有效的场景。
编辑:
就个人而言,如果你需要解决这个问题,我会推荐一个扩展方法:
public static IEnumerable<T> AsNotNull<T>(this IEnumerable<T> original)
{
return original ?? Enumerable.Empty<T>();
}
然后你可以调用:
foreach (int i in returnArray.AsNotNull())
{
// do some more stuff
}