Given the following stack trace:
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
I conclude that somehow the following block of code has retrieved a null from the input Dictionary's Keys collection. However, the input dictionary is an instance of Dictionary<string, string>
. The implementation of Dictionary<string, string>
makes that condition impossible. Upon adding an item with a null key, an exception is thrown.
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();
}
I've had this problem happen frequently because I made the mistake of allowing multiple threads to access the same dictionary. Make sure that this is not the case, because Dictionary
is not thread-safe.
(Incidentally, your method can be greatly simplified. Dictionary<K,V>
is already an IEnumerable<KeyValuePair<K,V>>
. You should be able to just do ToArray
on one.
It looks more like that your IDictionary
argument has an item with a Key
parameter which is null.
The parameter checking for the IDictionary
will probably be happening somewhere internally in the framework.
This exception happens if the dictionary key is null
. As the built-in Dictionary
class doesn't allow such keys, you might be using your own IDictionary
-compatible class which allows null
.
Not sure about the null but why aren't you using:
internal static KeyValuePair<string, string>[] Convert(IDictionary<string, string> from)
{
return from.ToArray();
}
Edit: As far as the null values are concerned. Do you have multiple threads accessing this IDictionary? Corruption is possible if you're not being thread safe. See this post for an example of corruption in the
Queue<T>
class. How can I modify a queue collection in a loop?
Threading might well be the cause, but it was a red herring in our case. You can also seem to have this problem if you have a Release build where a function was inlined. Consider this repro:
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);
}
}
On my machine this gives the following Debug build stack trace:
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)
But, it gives this stack trace in Release build:
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)
You'd be tempted to think with that last stack trace that it has to be things.TryGetValue
that causes the exception, when in fact it was the SomeSeeminglyUnrelatedFunction
function that got inlined in Main
.
So if you land here, please consider if you have a similar issue. (I realize this may not be a straight up answer to OP's question, but wanted to share nonetheless as it might help a future visitor.)
Could it possible be that another thread is affecting the dirctionary being passed into Convert?