291

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.

DigitalZebra
  • 39,494
  • 39
  • 114
  • 146
  • 4
    I suppose by the same reasoning it would be well-defined for *all* statements in C# to become no-ops when given a `null` value. Are you suggesting this for just `foreach` loops or other statements as well? – Ken Jun 21 '10 at 20:42
  • 8
    @ Ken... I'm thinking just foreach loops, because to me it seems apparent to the programmer that nothing would happen if the collection is empty or non-existent – DigitalZebra Jun 21 '10 at 20:47
  • 1
    Similar to http://stackoverflow.com/q/6455311/80161 and http://stackoverflow.com/a/11734449/80161 – Nathan Hartley Oct 09 '15 at 14:50
  • @Polaris878 since 'null' is the absence of knowledge. Not the knowledge that there's an empty list. Treating 'null' as something it's most definitely is not, is not obvious at all and might hide a sever bug – Rune FS May 03 '19 at 09:11
  • foreach on null collection is correct to throw the exception. Would you want a method called on a null reference to be a no-op too? Or serialization of a null collection to be equivalent to serialization of empty collection? Null and empty are two different things, and are treated in a consistent way by C# across all scenarios. – kaalus Nov 08 '20 at 18:23
  • For all the people here trying to justify why you can't `foreach` on a `null` collection, all I will say is you can do `using` on a `null` `IDisposable`. There's no true technical reason this had to be done this way; it's an oversight in the compiler and if there is sufficient demand for it to be changed then everyone should make their opinion known at https://github.com/dotnet/csharplang. I for one am sick and tired of getting null ref exceptions because I forgot to check if a collection is null. Totally unnecessary when no rational person would not prefer it be treated as empty. – Emperor Eto Feb 02 '22 at 17:00

12 Answers12

320

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));
}
theduck
  • 2,589
  • 13
  • 17
  • 23
Robaticus
  • 22,857
  • 5
  • 54
  • 63
  • 5
    Please excuse my ignorance, but is this efficient? Does it not result in a comparison on each iteration? – tinonetic Mar 29 '16 at 10:19
  • 24
    I don't believe so. Looking at the generated IL, the loop is after the is null comparison. – Robaticus Mar 30 '16 at 17:35
  • @Shimmy Was long answered by Robaticus...over a year ago :-) – tinonetic May 10 '17 at 06:55
  • Don't understand why he had to bother looking at the IL – Shimmy Weitzhandler May 10 '17 at 07:55
  • 15
    Holy necro... Sometimes you have to look at the IL to see what the compiler is doing to figure out if there are any efficiency hits. User919426 had asked whether it did the check for each iteration. Though the answer might be obvious to some people, it is not obvious to everyone, and providing the hint that looking at the IL will tell you what the compiler is doing, helps people fish for themselves in the future. – Robaticus May 10 '17 at 23:36
  • 2
    @Robaticus (even why later) the IL looks that why because the specification says so. The expansion of the syntactic sugar (aka foreach) is to evaluate the expression on the right side of "in" and call `GetEnumerator` on the result – Rune FS May 31 '17 at 09:28
  • 2
    @RuneFS - exactly. Understanding the specification or looking at the IL is a way to figure out the "why." Or to evaluate whether two different C# approaches boil down to the same IL. That was, essentially, my point to Shimmy above. – Robaticus Jun 01 '17 at 14:31
  • 2
    Might be relevant to future readers - why can't you do the same for a Dictionary: https://stackoverflow.com/questions/10431281/using-linq-to-objects-how-to-create-an-empty-dictionary-of-string-string-eas – JohnTortugo Jan 27 '18 at 00:36
  • 2
    Instead of calling them the compiler designers, you could also call them the language designers. The official C# Language Specification specifically says: _If `x` has the value `null`, a `System.NullReferenceException` is thrown at run-time_, in the description of the `foreach` statement (where `x` is what you foreach). Even without that sentence, it would follow from the spec that this was the case. So any correct C# implementation must have this behavior. – Jeppe Stig Nielsen Nov 28 '18 at 18:57
  • @kjbartel's answer (at " https://stackoverflow.com/a/32134295/401246 " is the best solution, because it doesn't: a) involve performance degradation of (even when not `null`) generalizing the whole loop to the LCD of `Enumerable` (as using `??` would) or (as other Answers here do) 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). – Tom Apr 23 '19 at 23:22
  • 1
    @user919426 no! the iteration is on the `IEnumerator` not the `IEnumerable` and since all the code does is to make sure that there's an `IEnumerable` available, the code will only be executed once – Rune FS May 03 '19 at 09:13
  • @RuneFS, you do realise that I was long answered over 3years ago, in March 2016, right?... moreso that even Shimmy answered after that and a comment was left to the same effect :)... Answers are appreciated though! – tinonetic May 03 '19 at 09:30
  • To reduce the memory footprint (unnecessary instantiations / disposals), you can declare `static readonly IReadOnlyList EmptyIntList = new List().AsReadOnly(); ` inside your class only once and then use it like `foreach (int i in array ?? EmptyIntList { ... }`. Unfortunately, this is not generic and needs to be done for each list type individually. – Matt Jul 15 '21 at 11:50
  • @Robaticus Looking at the IL is a possibly very dangerous way of determinating what the **code** does. It only tells you what that specific implementation of the **compiler** does, which is in terms dependend on the switches used in compilation. An optimizing compiler (or switch) could produce completely different code. The **only** way to find out what the **code** does is to look at the specs and the guaranties given there. – Holger Böhnke Apr 21 '22 at 13:54
163

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.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 10
    I agree, empty collections should always be returned... however i didn't write these methods :) – DigitalZebra Jun 21 '10 at 20:13
  • 21
    @Polaris, null coalescing operator to the rescue! `int[] returnArray = Do.Something() ?? new int[] {};` – JSBձոգչ Jun 21 '10 at 20:16
  • 2
    I disagree about a bad practice: see ⇒ if a function failed it could either return an empty collection — it is a call to constructor, memory allocation, and perhaps a bunch of a code to be executed. Either you could just return «null» → obviously there's only a code to return and a very short code to check is the argument is «null». It's just a performance. – Hi-Angel Dec 25 '14 at 06:54
  • I'd also add: ofc the coalescing operator creates an empty list either way. But that's already decision of a user: if one calls a function somewhere e.g. inside of a GUI, where a performance isn't significant, they may decide to do so. But if they're doing something that requires a performance, they just insert a check «if a result isn't null, do foreach». Though for high performance usually used C++ :Ь – Hi-Angel Dec 25 '14 at 07:11
  • @Hi-Angel how often are you likely to have a method failling (and thus constructing an object/empty collection) vs. how often would you have to do a null check (last one of course being always if you return null). You're suggestion would thus have a performance issue if the general scenario is that the method doesn't fail – Rune FS May 31 '17 at 09:31
  • @kjbartel's answer (at " https://stackoverflow.com/a/32134295/401246 " is the best solution, because it doesn't: a) involve performance degradation of (even when not `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). – Tom Apr 23 '19 at 23:22
61

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
}
huysentruitw
  • 27,376
  • 9
  • 90
  • 133
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 5
    Yes, but WHY doesn't foreach do a null check before getting the enumerator? – DigitalZebra Jun 21 '10 at 20:14
  • 13
    @Polaris878: Because it was never intended to be used with a null collection. This is, IMO, a good thing - since a null reference and an empty collection should be treated separately. If you want to work around this, there are ways.. .I'll edit to show one other option... – Reed Copsey Jun 21 '10 at 20:17
  • 1
    @Polaris878: I would suggest rewording your question: "Why SHOULD the runtime do a null check before getting the enumerator?" – Reed Copsey Jun 21 '10 at 20:23
  • 1
    I guess I'm asking "why not?" lol it seems like the behavior would still be well defined – DigitalZebra Jun 21 '10 at 20:31
  • 2
    @Polaris878: I guess, the way I think of it, returning null for a collection is an error. The way it is now, the runtime gives you a meaningful exception in this case, but it's easy to work around (ie: above) if you don't like this behavior. If the compiler hid this from you, you'd lose the error checking at runtime, but there'd be no way to "turn it off"... – Reed Copsey Jun 21 '10 at 20:43
  • @Polaris878: The behavior of enumerating a null reference *is* well-defined. It is defined as throwing a `NullReferenceException`; I don't think it's allowed to do anything else. – supercat Jan 29 '14 at 17:07
  • @kjbartel's answer (at " https://stackoverflow.com/a/32134295/401246 " is the best solution, because it doesn't: a) involve performance degradation of (even when not `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). – Tom Apr 23 '19 at 23:24
  • 1
    `.AsNotNull()` is IMHO the most convenient way, it works as shown above with foreach and also with LINQ (`var query = from x in returnArray.AsNotNull() ...`). But in my opinion, the best way would be if the C# compiler team would introduce an `in?` operator which implicitly uses something like `.AsNotNull()`. – Matt Jul 16 '21 at 08:16
  • @Polaris878 The way I see it, `foreach` expects an instance of `IEnumerable` or `IEnumerable` and you passed it `null` instead. That's an error. You might consider it inconvenient to have to check if your variable is `null`, but if you don't you're just ignoring a potential error state. (Whether or not it was a good design decision to make `null` a thing in C# in the first place is a different question entirely.) – Clonkex Jul 26 '22 at 00:46
23

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
        });
Devesh
  • 4,500
  • 1
  • 17
  • 28
  • 2
    @kjbartel beat you to this by over a year (at " https://stackoverflow.com/a/32134295/401246 "). ;) This is the best solution, because it doesn't: a) involve performance degradation of (even when not `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. – Tom Apr 23 '19 at 23:16
12

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);
});
Jay
  • 56,361
  • 10
  • 99
  • 123
  • Just missing a closing parenthesis in the 3rd example. Otherwise, beautiful code that can be extended further in interesting ways (for loops, reversing, leaping, etc). Thanks for sharing. –  Feb 16 '17 at 17:08
  • Thanks for such a wonderful code, But i didn't understand the first methods,why you pass console.writeline as parameter,though its printing the array elements.but didnt understand – Ajay Singh Dec 14 '17 at 07:37
  • @AjaySingh `Console.WriteLine` is just an example of a method that takes one argument (an `Action`). The items 1, 2 and 3 are showing examples of passing functions to the `.ForEach` extension method. – Jay Dec 15 '17 at 18:25
  • @kjbartel's answer (at " https://stackoverflow.com/a/32134295/401246 " is the best solution, because it doesn't: a) involve performance degradation of (even when not `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). – Tom Apr 23 '19 at 23:25
  • @Tom - but that answer applies only to `List`, it's the only collection that has `.ForEach()`, 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`. – yzorg Jul 14 '22 at 17:03
6

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.

JAB
  • 20,783
  • 6
  • 71
  • 80
4

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);
      }
   }
}
BFree
  • 102,548
  • 21
  • 159
  • 201
3

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.

H H
  • 263,252
  • 30
  • 330
  • 514
2

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
    }
}
Lucero
  • 59,176
  • 9
  • 122
  • 152
  • 3
    so? Why can't it simply check if it is null first and skip the loop? AKA, exactly what is shown in the extension methods? The question is, is it better to default to skip the loop if null or to throw an exception? I think it's better to skip! Seems likely that null containers are meant to be skipped rather than looped over since loops are meant to do something *IF* the container is non-null. – AbstractDissonance Feb 25 '16 at 22:25
  • @AbstractDissonance You could argue the same with all `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. – Lucero Feb 25 '16 at 22:45
  • 2
    I don't think so. The foreach is meant to operate over the collection and is different than referencing a null object directly. While one could argue the same, I bet if you analyzed all the code in the world, you would have most foreach loops have null checks of some kind in front of them only to bypass the loop when the collection is "null"(which is hence treated the same as empty). I don't think anyone considers looping over a null collection as something they want to and would rather simply ignore the loop if the collection is null. Maybe, rather, a foreach?(var x in C) could be used. – AbstractDissonance Feb 26 '16 at 00:03
  • 1
    The point I'm mainly trying to make is that it creates a bit of litter in the code since one has to check every time for no good reason. The extensions, of course, work but a language feature could be added to avoid these things without much issue. (mainly I think the current method produces hidden bugs since the programmer may forget to put the check and hence an exception... because either he expects the check to occur somewhere else before the loop or is thinking that it was pre-initialized(which it may or may have changed). But in either cause, the behavior would be the same as if empty. – AbstractDissonance Feb 26 '16 at 00:07
  • @AbstractDissonance Well, with some proper static analysis you know where you could have nulls and where not. If you get a null where you don't expect one it's better to fail instead of silently ignoring problems IMHO (in the spirit of [failing fast](http://martinfowler.com/ieeeSoftware/failFast.pdf)). Therefore I feel that this is the correct behavior. – Lucero Feb 26 '16 at 00:08
2

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
    });
Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
Alielson Piffer
  • 343
  • 2
  • 10
0

I think it should check for null. Saves code and headache. Here's a simple extension method I made to solve this problem:

    /// <summary>
    /// Loop through nullable list
    /// </summary>
    public static IEnumerable<T> OrEmptyIfNull<T>(this IEnumerable<T> source)
    {
        return source ?? Enumerable.Empty<T>();
    }

Usage:

     @foreach (var e in account.Items.OrEmptyIfNull())
     {
         <tr class="odd:bg-gray-100 cursor-pointer">
      ...
tqrecords
  • 542
  • 1
  • 5
  • 20
-4
SPListItem item;
DataRow dr = datatable.NewRow();

dr["ID"] = (!Object.Equals(item["ID"], null)) ? item["ID"].ToString() : string.Empty;
Tunaki
  • 132,869
  • 46
  • 340
  • 423