简体   繁体   中英

Adding an item to a dictionary results in a NullReferenceException

The following code has only thrown a NullReferenceException a handful of times over the last several months, but I'm not exactly sure why. The code isn't mine, but it looks pretty straight forward to me.

Type pageType = page.GetType();

if (_pages.TryGetValue(pageType, out value))
    return value;

// The following line throws the exception
return _pages[pageType] = new MyPage(_section.Pages[page]);

[NullReferenceException: Object reference not set to an instance of an object.] System.Collections.Generic.Dictionary 2.Insert(TKey key, TValue value, Boolean add) +210 System.Collections.Generic.Dictionary 2.set_Item(TKey key, TValue value) +11

The only thing I can think of is that pageType is null when it's being used as a dictionary key, but apparently that is not possible .

The code that calls it is simple:

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    _mypage = GetPage();
}

I also thought that the error might be with the _section.Pages , but section is never null and never sets anything. If .Pages[page] returns null, the MyPage constructor simply returns. So what am I missing?

I had this issue and it turned out to be threading related.

By placing a sync lock around the line that inserts into the dictionary you can protect against the error:

This must be added as a class level definition:

private static object _sync = new object();

This is the insert statement surrounded by a sync lock:

lock (_sync)
{
    return _pages[pageType] = new MyPage(_section.Pages[page]);
}

This is the post that solved it for me: Throw a NullReferenceException while calling the set_item method of a Dictionary object in a multi-threading scenario

I think it is throwing an exception because there is no element in the dictionary for the key pageType , and the accessor is returning null.

Try

MyPage newPage = new MyPage(_section.Pages[page]);
_pages.Add(pageType, newPage);
return newPage;

or if you are trying to reuse the entry if it exists:

MyPage newPage = new MyPage(_section.Pages[page]);
if (_pages.ContainsKey(pageType))
   _pages[pageType] = newPage;
else
   _pages.Add(pageType, newPage);

maybe the dictionary user defines somewhere else a custom IEqualityComparer that fails under some circumstances. Check where the code creates the dictionary to see if a custom comparer is passed. Maybe the comparer as well can be null, but this means this code never run...

I would split them out for clarity, then see whats happening.

var section = _section.Pages[page];
var newPage = new MyPage(section);
_pages.Add(pageType,newPage);
return newPage;

I think either _pages or pageType object is null. Another chance is _section object.

Since TryGetValue didn't failed it looks to be caused by _section.Pages[page]. Since exception comes from Dictionary.Insert method, most probably, it's caused by equality/hash code implementation for the page. Are there custom implementations of IEqualityComparer or Equals/GetHashCode methods for page type? How these dictionaries are created?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM