2010-02-17 63 views
6

鑑於以下堆棧跟蹤:這個詞典如何<TKey,TValue>例外成爲可能?

MESSAGE: Value cannot be null.Parameter name: key 
SOURCE: mscorlib 
TARGETSITE: Void ThrowArgumentNullException(System.ExceptionArgument) 
STACKTRACE: 
    at System.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument) 
    at System.Collections.Generic.Dictionary'2.FindEntry(TKey key) 
    at System.Collections.Generic.Dictionary'2.get_Item(TKey key) 
    at MyCompany.MAF.Agent.ServiceContracts.ConvertUtils.Convert(Dictionary'2 from) in D:\Development\MAF\Agent\MyCompany.MAF.Agent\ServiceContracts\ConvertUtils.cs:line 11 

我的結論是莫名其妙下面的代碼塊已檢索從輸入字典的鍵集合空。但是,輸入字典是Dictionary<string, string>的一個實例。Dictionary<string, string>的實施使這種情況變得不可能。用空鍵添加項目時,會引發異常。

internal static KeyValuePair<string, string>[] Convert(IDictionary<string, string> from) 
{ 
    List<KeyValuePair<string, string>> ret = new List<KeyValuePair<string, string>>(); 
    foreach (string key in from.Keys) 
     ret.Add(new KeyValuePair<string, string>(key, from[key])); 
    return ret.ToArray(); 
} 
+0

因爲它沒有真正回答你的問題(我最好的猜測是它是線程相關的)但是你的循環是多餘的from.ToArray()會產生相同的結果 – 2010-02-17 19:04:33

回答

11

我有這個問題經常發生,因爲我犯了允許多個線程訪問相同字典的錯誤。請確保情況並非如此,因爲Dictionary不是線程安全的。

(順便說一句,你的方法可以大大簡化Dictionary<K,V>已經是IEnumerable<KeyValuePair<K,V>>你應該能夠只是做ToArray一個

+0

我已經嘗試過並且未能創建競爭條件與線程。即使存在線程問題,key永遠不可能從Keys集合初始化爲空 – goofballLogic 2010-02-17 18:55:16

+0

有關ToArray方法的好處 - 這不能解釋異常,但我懷疑它會阻止它發生。 – goofballLogic 2010-02-17 18:57:31

+0

不,你不能有一個空鍵,但是'Dictionary'使用的內部方法在進入某些狀態時仍然會拋出這個異常。我已經看到它發生了很多,特別是在ASP.NET應用程序中使用不受保護的靜態字典時。 – Jacob 2010-02-17 18:58:47

3

它看起來更像是你的IDictionary說法有一個Key參數是空的項目。

IDictionary的參數檢查可能會在框架內部的某處發生。

+1

字典不能用null鍵填充項目 – goofballLogic 2010-02-17 18:51:07

+0

@goofballogic,true,但你只會在運行時發現如果你的鍵字符串爲空,然後得到一個異常... – 2010-02-17 18:54:41

+1

不,字典<字符串,字符串>拋出一個異常,如果有東西試圖用null鍵填充它。顯示的例外是檢索值,而不是添加/插入它。 – goofballLogic 2010-02-17 18:56:15

2

如果字典關鍵字是null,則會發生此異常。由於內置Dictionary類不允許使用此類密鑰,因此您可能會使用自己的IDictionary兼容類,該類允許使用null

+0

中的一個點引用沒有傳入的字典是一個字典<字符串,字符串> – goofballLogic 2010-02-24 11:15:33

2

不知道的空,但你爲什麼不使用:。

internal static KeyValuePair<string, string>[] Convert(IDictionary<string, string> from) 
{ 
    return from.ToArray(); 
} 

編輯:至於空值都在關注你有多個線程訪問這個IDictionary的腐敗是可能的,如果你不是線程安全的看到這個職位在

一個腐敗的例子?
Queue<T> 

class。 How can I modify a queue collection in a loop?

+0

好點 - 這不能解釋例外,但我懷疑它會阻止它發生。 – goofballLogic 2010-02-17 18:57:16

+0

@goofballlogic:查看我的更新。如果IDictionary越來越腐敗,那麼簡化該方法可能不是解決方案。您可能需要在IDictionary周圍實現一些鎖定。 – 2010-02-17 18:58:37

1

是否有可能是另一個線程正在影響被傳遞到Convert的dirctionary?

1

線程可能是原因,但在我們的例子中它是一條紅色鯡魚。如果您有版本構建,您也可以似乎有一個函數被內聯的問題。考慮這個攝製:

class Program 
{ 
    static string someKey = null; 

    static void Main(string[] args) 
    { 
     try 
     { 
      object thing; 

      if (SomeSeeminglyUnrelatedFunction(someKey, out thing)) Console.WriteLine("Found"); 

      things.TryGetValue(someKey, out thing); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.StackTrace.ToString()); 
      throw; 
     } 

     Console.ReadKey(); 
    } 

    private static Dictionary<string, object> stuff = new Dictionary<string, object>(); 
    private static Dictionary<string, object> things = new Dictionary<string, object>(); 

    private static bool SomeSeeminglyUnrelatedFunction(string key, out object item) 
    { 
     return stuff.TryGetValue(key, out item); 
    } 
} 

在我的機器此給出以下調試版本堆棧跟蹤:

at System.Collections.Generic.Dictionary`2.FindEntry(TKey key) 
at System.Collections.Generic.Dictionary`2.TryGetValue(TKey key, TValue& value) 
at MyApp.Program.SomeSeeminglyUnrelatedFunction(String key, Object& item) 
at MyApp.Program.Main(String[] args) 

,它給發佈此堆棧跟蹤建立

at System.Collections.Generic.Dictionary`2.FindEntry(TKey key) 
at System.Collections.Generic.Dictionary`2.TryGetValue(TKey key, TValue& value) 
at MyApp.Program.Main(String[] args) 

你會試圖用最後一個堆棧跟蹤來看,它things.TryGetValue導致異常,實際上它是在Main中內聯的SomeSeeminglyUnrelatedFunction函數。

所以,如果你在這裏,請考慮你是否有類似的問題。 (我意識到這可能不是OP的直接答案,但希望分享,因爲它可能有助於未來的訪問者。)

相關問題