Why does .NET foreach loop throw NullRefException when collection is null?

So I frequently run into this situation... where Do.Something(...) returns a null collection, like so:

int[] returnArray = Do.Something(...);

Then, I try to use this collection like so:

foreach (int i in returnArray)
{
    // do some more stuff
}

I'm just curious, why can't a foreach loop operate on a null collection? It seems logical to me that 0 iterations would get executed with a null collection... instead it throws a NullReferenceException . Anyone know why this could be?

This is annoying as I'm working with APIs that aren't clear on exactly what they return, so I end up with if (someCollection != null) everywhere...

Edit: Thank you all for explaining that foreach uses GetEnumerator and if there is no enumerator to get, the foreach would fail. I guess I'm asking why the language/runtime can't or won't do a null check before grabbing the enumerator. It seems to me that the behavior would still be well defined.


Well, the short answer is "because that's the way the compiler designers designed it." Realistically, though, your collection object is null, so there's no way for the compiler to get the enumerator to loop through the collection.

If you really need to do something like this, try the null coalescing operator:

    int[] array = null;

    foreach (int i in array ?? Enumerable.Empty<int>())
    {
        System.Console.WriteLine(string.Format("{0}", i));
    }

A foreach loop calls the GetEnumerator method.
If the collection is null , this method call results in a NullReferenceException .

It is bad practice to return a null collection; your methods should return an empty collection instead.


There is a big difference between an empty collection and a null reference to a collection.

When you use foreach , internally, this is calling the IEnumerable's GetEnumerator() method. When the reference is null, this will raise this exception.

However, it is perfectly valid to have an empty IEnumerable or IEnumerable<T> . In this case, foreach will not "iterate" over anything (since the collection is empty), but it will also not throw, since this is a perfectly valid scenario.


Edit:

Personally, if you need to work around this, I'd recommend an extension method:

public static IEnumerable<T> AsNotNull<T>(this IEnumerable<T> original)
{
     return original ?? Enumerable.Empty<T>();
}

You can then just call:

foreach (int i in returnArray.AsNotNull())
{
    // do some more stuff
}
链接地址: http://www.djcxy.com/p/75156.html

上一篇: 空传播算子和动态变量

下一篇: 为什么.NET foreach循环在收集为空时抛出NullRefException?