Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# null coalescing operator returning null

Tags:

c#

.net

Recently my co-worker showed me a block of code that was not working correctly:

public class SomeClass
{
    private IList<Category> _categories;

    public void SetCategories()
    {
        _categories = GetCategories() ?? new List<Category>();
        DoSomethingElse();
    }

    public IList<Category> GetCategories()
    {
        return RetrieveCategories().Select(Something).ToList();
    }
}

(I am aware that the operator is superfluous since the linq ToList will always return a list, but that is how the code was set up).

The problem was that _categories was null. In the debugger, setting a breakpoint on _categories = GetCategories() ?? new List<Category>(), then stepping over to DoSomethingElse(), _categories would still be null.

Directly setting _categories to GetCategories() worked fine. Splitting the ?? in to a full if statement worked fine. The null coalescing operator did not.

It is an ASP.NET application, so a different thread could possibly be interfering, but it was on his machine, with only him connected in a browser. _cateogories is not static, or anything.

What I'm wondering is, how could this possibly happen?

Edit:

Just to add to the bizarreness, _categories is never set anywhere besides that function (apart from initializing the class).

The exact code is like so:

public class CategoryListControl
{
    private ICategoryRepository _repo;
    private IList<Category> _categories;

    public override string Render(/* args */)
    {
        _repo = ServiceLocator.Get<ICategoryRepository>();
        Category category = _repo.FindByUrl(url);
        _categories = _repo.GetChildren(category) ?? new List<Category>();
        Render(/* Some other rendering stuff */);
    }
}

public class CategoryRepository : ICategoryRepository
{
    private static IList<Category> _categories;

    public IList<Category> GetChildren(Category parent)
    {
        return _categories.Where(c => c.Parent == parent).ToList<Category>();
    }
}

Even it GetChildren magically returned null, CategoryListControl._categories still should never, ever be null. GetChildren should also never, ever return null because of IEnumerable.ToList().

Edit 2:

Trying out @smartcaveman's code, I found out this:

Category category = _repo.FindByUrl(url);

_categories = _repo.GetChildren(category) ?? new List<Category>();

_skins = skin; // When the debugger is here, _categories is null

Renderer.Render(output, _skins.Content, WriteContent); // When the debugger is here, _categories is fine.

As well, when testing if(_categories == null) throw new Exception(), _categories was null on the if statement, then stepping over the exception was not thrown.

So, it seems like this is a debugger bug.

like image 364
Snea Avatar asked Feb 01 '11 20:02

Snea


2 Answers

This could be a problem with the debugger rather than with the code. Trying printing out the value or doing a null check after the statement with the coalesce operator.

like image 66
Tim H Avatar answered Oct 03 '22 10:10

Tim H


The null-coalescing operator is not broken. I use it in a similar manner all the time quite successfully. Something else is going on.

like image 29
Greg D Avatar answered Oct 03 '22 09:10

Greg D