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.
null
value. Are you suggesting this for just foreach
loops or other statements as well?
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.
int[] returnArray = Do.Something() ?? new int[] {};
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
}
It is being answer long back but i have tried to do this in the following way to just avoid null pointer exception and may be useful for someone using C# null check operator ?.
//fragments is a list which can be null
fragments?.ForEach((obj) =>
{
//do something with obj
});
null
) generalizing the whole loop to the LCD of Enumerable
(as using ??
would), b) require adding an Extension Method to every Project, and c) require avoiding null
IEnumerable
s (Pffft! Puh-LEAZE! SMH.) to begin with.
Another extension method to work around this:
public static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
{
if(items == null) return;
foreach (var item in items) action(item);
}
Consume in several ways:
(1) with a method that accepts T
:
returnArray.ForEach(Console.WriteLine);
(2) with an expression:
returnArray.ForEach(i => UpdateStatus(string.Format("{0}% complete", i)));
(3) with a multiline anonymous method
int toCompare = 10;
returnArray.ForEach(i =>
{
var thisInt = i;
var next = i++;
if(next > 10) Console.WriteLine("Match: {0}", i);
});
Console.WriteLine
is just an example of a method that takes one argument (an Action<T>
). The items 1, 2 and 3 are showing examples of passing functions to the .ForEach
extension method.
null
) generalizing the whole loop to the LCD of Enumerable
(as using ??
would), b) require adding an Extension Method to every Project, or c) require avoiding null
IEnumerable
s (Pffft! Puh-LEAZE! SMH.) to begin with (cuz, null
means N/A, whereas empty list means, it's appl. but is currently, well, empty!, i.e. an Empl. could have Commissions that's N/A for non-Sales or empty for Sales).
List<T>
, it's the only collection that has .ForEach<T>()
, which is dumb, IMO. So you can't use that answer after string.Split()
for example, without another perf trade-off of converting the array of strings returned to a list just to use .ForEach()
. All these trade-offs are just dumb, they should fix it, or never return null
from built-in methods (I don't think it's viable to always return List<T>
.
Because a null collection is not the same thing as an empty collection. An empty collection is a collection object with no elements; a null collection is a nonexistent object.
Here's something to try: Declare two collections of any sort. Initialize one normally so that it's empty, and assign the other the value null
. Then try adding an object to both collections and see what happens.
Just write an extension method to help you out:
public static class Extensions
{
public static void ForEachWithNull<T>(this IEnumerable<T> source, Action<T> action)
{
if(source == null)
{
return;
}
foreach(var item in source)
{
action(item);
}
}
}
It is the fault of Do.Something()
. The best practice here would be to return an array of size 0 (that is possible) instead of a null.
Because behind the scenes the foreach
acquires an enumerator, equivalent to this:
using (IEnumerator<int> enumerator = returnArray.getEnumerator()) {
while (enumerator.MoveNext()) {
int i = enumerator.Current;
// do some more stuff
}
}
null
references, e.g. when accessing members. Typically this is an error, and if it isn't then it's simple enough to handle this for instance with the extension method which another user has provided as answer.
I think the explanation of why exception is thrown is very clear with the answers provided here. I just wish to complement with the way I usually work with these collections. Because, some times, I use the collection more then once and have to test if null every time. To avoid that, I do the following:
var returnArray = DoSomething() ?? Enumerable.Empty<int>();
foreach (int i in returnArray)
{
// do some more stuff
}
This way we can use the collection as much as we want without fear the exception and we don't polute the code with excessive conditional statements.
Using the null check operator ?.
is also a great approach. But, in case of arrays (like the example in the question), it should be transformed into List before:
int[] returnArray = DoSomething();
returnArray?.ToList().ForEach((i) =>
{
// do some more stuff
});
ForEach
method is one of the things I hate in a codebase.
SPListItem item;
DataRow dr = datatable.NewRow();
dr["ID"] = (!Object.Equals(item["ID"], null)) ? item["ID"].ToString() : string.Empty;
Success story sharing
GetEnumerator
on the result