2011-03-28 51 views
4

以下代碼在過去幾個月中僅引發了少數幾次NullReferenceException,但我不完全確定原因。代碼不是我的,但它看起來很直截了當。將項添加到字典中會導致NullReferenceException

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

我能想到的唯一的事情是,當它被用來作爲字典的鍵,但顯然that is not possiblepageType爲空。

調用它是簡單的代碼:

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

我也認爲該錯誤可能與_section.Pages,但部分是從來沒有空,不落任何東西。如果.Pages[page]返回null,則簡單地返回MyPage構造函數。那麼我錯過了什麼?

+0

您的「MyPage」對象是否覆蓋「GetHashCode」或「Equals」?這些是Dictionary類可能會在您的對象上創建的兩個可能的調用。 – 2011-03-28 16:24:08

回答

1

我認爲這是拋出一個異常,因爲沒有在字典中的鍵元素pageType,並且訪問器返回null。

嘗試

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

,或者如果你想如果存在重複使用的條目:

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

當它不存在應該創建條目時,其索引器沒有訪問字典? http://en.csharp-online.net/BCL_Generics%E2%80%94Adding_and_Updating_Dictionary_Items – Brandon 2011-03-28 16:02:26

+0

詞典索引器設置器在添加新元素時從不拋出異常。它可能被getter引發,但在這種情況下,它將是KeyNotFoundException,而不是NullReferenceException。 – 2011-03-28 16:04:01

0

我會分裂出來的清晰度,然後看看發生了什麼。

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

我現在有,但由於這種錯誤很少發生,我從來沒有能夠重現或調試它。它通常只在生產環境中顯示。 – Brandon 2011-03-28 16:12:56

0

我認爲_pages或pageType對象爲null。另一個機會是_section對象。

+0

dev,_pages和_section不爲空。爲了保持示例簡潔,我刪除了空白檢查。而pageType不能爲null,因爲GetType永遠不會返回null。 – Brandon 2011-03-28 16:00:32

+0

如果所提供的代碼引發異常,則它們中的任何一個都不能爲null:當調用TryGetValue時,_pages和pageType會在最後一行的上方使用,而且如果pageType爲null,則會引發ArgumentNullException。 _section也不能爲null,因爲在這種情況下我們不應該進入Dictionary.Insert方法。 – 2011-03-28 16:08:38

+0

@Brandon:如果我們使用代理攔截GetType調用,實際上GetType可以返回null,但它確實不是你的情況。 – 2011-03-28 16:12:41

0

由於TryGetValue沒有失敗,它看起來是由_section.Pages [page]引起的。由於異常來自Dictionary.Insert方法,很可能它是由頁面的等號/哈希碼實現引起的。是否有頁面類型的IEqualityComparer或Equals/GetHashCode方法的自定義實現?這些字典是如何創建的?

+0

詞典在課堂上被宣佈爲只讀。他們不覆蓋任何方法。 – Brandon 2011-03-28 16:48:20

+0

@Brandon:如何創建字典(未聲明)?你是否將比較器傳遞給字典構造函數?是否有Equals/GetHashCode覆蓋頁面類型?當然,字典沒有重寫,因爲它沒有意義。 – 2011-03-28 17:17:30

1

也許詞典用戶定義其他的自定義的IEqualityComparer,在某些情況下失敗的地方。檢查代碼創建字典的位置,以查看是否傳遞了自定義比較器。也許比較器也可以爲空,但這意味着這段代碼從不運行...

2

我有這個問題,它原來是線程相關。

通過將圍繞插入到可以抵禦錯誤的字典行同步鎖:

這必須添加爲一個類級別的定義:

private static object _sync = new object(); 

這是插入語句被同步鎖定包圍:

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

這是解決它,我的帖子:Throw a NullReferenceException while calling the set_item method of a Dictionary object in a multi-threading scenario

+1

儘管此鏈接可能會回答問題,但最好在此處包含答案的基本部分,並提供供參考的鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 – djv 2014-11-05 15:43:42

+2

好點@Verdolino。我相應地編輯了我的帖子。 – AndyM 2014-11-05 16:29:10