Pete
Pete

Reputation: 58422

linq null reference error with orderby but firstordefault works

I have the following code:

IEnumerable<VariantChild> children = src.Variants
    .Where(v => !v.ExcludeFromWebsite && !v.ExcludeFromEcommerce)
    .SelectMany(v => v.Children)
    .Where(c => c.Price > 0 && !c.ExcludeFromWebsite && !c.ExcludeFromEcommerce);

if (children.Any())
{
    VariantChild child  = children.OrderBy(c => c.Price).FirstOrDefault();  // this line is throwing a null reference error

    if (child != null)
    {
        dest.Price = child.Price;
    }
}

But it is throwing a null refence exception on the line highlighted. If I remove the orderby, the code works so I thought it may be to do with the price being null - but it can't be as it is a double.

Having stepped through the code, the .Any() returns true, but if I change that to .Count(), I get the null exception

If I step through and check the children object - I can see the results view is null so shouldn't .Any() return false (although why does FirstOrDefult() return a variant child?

Anyone any ideas what is causing the null exception?

Here is a screenshot of the code as I stepped into it:

Screenshot

Upvotes: 1

Views: 600

Answers (1)

Orace
Orace

Reputation: 8359

Keep in mind that linq expressions are not evaluated when created but only when necessary (ex: ToList, or in your case, OrderBy then FirstOrDefault. See deferred execution.). So the null reference exception can be in the evaluation of children.

Supposing that ExcludeFromWebsite and ExcludeFromEcommerce are booleans and can't be null and Price is a double and can't be null. Only remain Children witch is an IEnumerable (because used in SelectMany) so it can be null.

Furthermore, in your screen shot, the stack trace refer to the SelectManyIterator.

You should check for Children to not be null :

IEnumerable<VariantChild> children = src.Variants
  .Where(v => !v.ExcludeFromWebsite && !v.ExcludeFromEcommerce)
  .SelectMany(v => v.Children ?? Enumerable.Empty<T>()) // T is the type of element in Children
  .Where(c => c.Price > 0 && !c.ExcludeFromWebsite && !c.ExcludeFromEcommerce);

Upvotes: 3

Related Questions