Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Foreach throws NullReferenceException on not null IEnumerable with elements

I have encountered in my code similiar situation to the one presented in code below. The problem is that for some reason iterating in foreach loop throws NullReferenceException.

My question is, why this happens?

If I create iterator that returns empty element myself, foreach handles it, and simply prints empty line.

Result of following code is: test, test, NullReferenceException.

using System;
using System.Collections.Generic;
using System.Linq;

public class NestedB
{
    public string Test {get;set;}
}

public class NestedA
{
    public List<NestedB> NestedCollection {get;set;}
}

public class Program
{
    public static void Main()
    {
        var listOfA = new List<NestedA>
        {
            new NestedA
            {
                NestedCollection = new List<NestedB> 
                {
                    new NestedB {Test = "test"},
                    new NestedB {Test = "test"}
                }
            },
            new NestedA ()
        };
        
        var listOfB = listOfA.SelectMany(x => x.NestedCollection);
        
        foreach (var item in listOfB)
        {
            if (item != null)
            {
                Console.WriteLine(item.Test);
            }
        }
    }
    
}

Stacktrace:

Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Linq.Enumerable.SelectManySingleSelectorIterator`2.MoveNext()
   at Program.Main()
Command terminated by signal 6
like image 403
M Pal Avatar asked Oct 12 '25 06:10

M Pal


1 Answers

This is the problem:

listOfA.SelectMany(x => x.NestedCollection)

Your second NestedA instance doesn't have a NestedCollection, so it's trying to find "all the items in a null reference". You'd have exactly the same problem if you did this manually:

var nestedA = new NestedA();
// This will throw an exception, because nestedA.NestedCollectoin is null
foreach (var nestedB in nestedA.NestedCollection)
{
}

The simplest fix to this would be to make NestedCollection a read-only property, but initialize it to start with:

public List<NestedB> NestedCollection { get; } = new List<NestedB>();

Then you'll need to modify the initialization of your first NestedA to use a collection initializer:

new NestedA
{
    NestedCollection =
    {
        new NestedB { Test = "test" },
        new NestedB { Test = "test" }
    }
}

If you don't want to do that, you could change the SelectMany call instead:

var listOfB = listOfA.SelectMany(x => x.NestedCollection ?? Enumerable.Empty<NestedB>())
like image 50
Jon Skeet Avatar answered Oct 14 '25 19:10

Jon Skeet