1

I came across this problem but have been unable to figure out what is causing it and have been unable to replicate it, despite my attempts here https://dotnetfiddle.net/xDVa2a. My classes are structured like so:

public abstract class ProductNode
{
    public ProductCategory ParentCategory { get; set; }
}

public class ProductCategory : ProductNode { }

public class TreeNode<T> where T : class
{
    private readonly T _value;

    public T Value() {
        return _value;
    }

    public TreeNode(T value) {
        _value = value;
    }
}

In my code I create a TreeNode of type ProductNode with the constructor argument as null and use LINQ to filter an IQueryable to compare the ProductNode against the value in the TreeNode.

IQueryable<ProductNode> allProductNodes = _context.ProductNodes;
TreeNode<ProductNode> treeNode = new TreeNode<ProductNode>(null);
List<ProductNode> productNodes = allProductNodes
    .Where(node => node.ParentCategory == treeNode.Value()).ToList(); // NullReferenceException

This throws a NullReferenceException, however if I tweak my query to compare against null it works.

List<ProductNode> productNodes = allProductNodes
    .Where(node => node.ParentCategory == null).ToList(); // Works

List<ProductNode> productNodes = allProductNodes
    .Where(node => node.ParentCategory == (treeNode.Value() ?? null)).ToList(); // Alternative, working solution

What is causing the compiler to throw the exception?

drmathias
  • 39
  • 6
  • Does anything in there happen to overload the == operator? That's about the only thing I can imagine going wrong here... – Nyerguds Jul 06 '18 at 03:13
  • Your `TreeNode` class doesn't even compile. Please show real code that we can see your issue. – Enigmativity Jul 06 '18 at 04:16
  • @Enigmativity My question was edited but now I have changed it back to how it was. – drmathias Jul 06 '18 at 10:04
  • @drmathias My bad, didn't realize the second function was `_value = value;`. The expression body wasn't the issue, so that didn't need to be changed. `public TreeNode(T value) => _value = value;` would work. – AustinWBryan Jul 06 '18 at 20:12
  • Also, is this really a duplicate? This is more like the inverse, asking "Why isn't there a null reference exception?" not "I have one, how can I fix this?" – AustinWBryan Jul 06 '18 at 20:13
  • Sidenote, why is `Value()` not a property? It should either be named `GetValue()` or be replaced with `Value => _value;` – AustinWBryan Jul 06 '18 at 20:15

3 Answers3

0

You are using the "??" operator which returns treeNode.Value() if not null, and the right hand side if null.

So you are returning null in both cases, basically null.ToList() is your end result and where your Null Ref comes from.

ForceMagic
  • 6,230
  • 12
  • 66
  • 88
  • That is the working solution that I am using, though your answer highlights my confusion. If I simply compare node.ParentCategory with treeNode.Value(), which should be null, it throws a NullReferenceException. When I use the ?? operator it does not throw the exception, because for some reason explicitly using the keyword is fine. – drmathias Jul 06 '18 at 02:02
  • @drmathias When you compare node.ParentCategory with treeNode.Value() which should be null, are you still dereferencing it with .List() ? – ForceMagic Jul 06 '18 at 02:10
  • 1
    OP is using `.ToList()` in all cases. The argument is that `.Where(node => node.ParentCategory == treeNode.Value()).ToList();` this causes `NullReferenceException`, but replacing `treeNode.Value()` with `null` does not, and replacing it with `(treeNode.Value() ?? null)` does not throw either. Besides, `IQueryable.Where` should not return `null`, it will either return an `IEnumerable` (perhaps empty), or throw `ArgumentNullException` because a parameter is `null` (the epxpresion or the source collection) or throw whatever inside throws. Thus, it will never reduce to `null.ToList()`. – Theraot Jul 06 '18 at 02:57
0

Using ?? has no point if you're going to return null if it is null. What you probably want to do instead is this:

treeNode.Value()?.ToList();

That will make it so that, if treeNode.Value() is not null, it will call .ToList() on it. If it is null, however, .ToList() won't be called and that should get rid of that error.

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
  • That's the thing, `?? null` should have no point, but it is preventing the compiler from throwing the exception. I'm calling `ToList()` on the `Where()` clause in all cases, not on `treeNode.Value()`and as @Theraot pointed out `.Where()` should never return `null` or throw `NullReferenceException`. – drmathias Jul 06 '18 at 10:22
0

Have you tried this:

List<ProductNode> productNodes = allProductNodes.ToList()
.Where(node => node.ParentCategory == (treeNode.Value() ?? null));

I am afraid calling a function (in this case treeNode.Value()) on IQueryable may result unusual behavior.

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42