Как возможно это исключение из словаря <TKey, TValue>? - PullRequest
6 голосов
/ 17 февраля 2010

Учитывая следующую трассировку стека:

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();
}

Ответы [ 6 ]

12 голосов
/ 17 февраля 2010

У меня часто возникала эта проблема, потому что я допустил ошибку, позволив нескольким потокам обращаться к одному и тому же словарю. Убедитесь, что это не так, потому что Dictionary не является потокобезопасным.

(Кстати, ваш метод может быть значительно упрощен. Dictionary<K,V> - это уже IEnumerable<KeyValuePair<K,V>>. Вы можете просто сделать ToArray на одном.

3 голосов
/ 17 февраля 2010

Похоже, что ваш аргумент IDictionary содержит элемент с параметром Key, равным нулю.

Проверка параметров для IDictionary, вероятно, будет происходить где-то внутри фреймворка.

2 голосов
/ 03 августа 2016

Резьба вполне может быть причиной, но в нашем случае это была красная сельдь. Вы также можете казаться иметь эту проблему, если у вас есть Release build , где была встроена функция. Посмотрите на это 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);
    }
}

На моей машине это дает следующее Отладочная сборка трассировка стека:

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, что вызывает исключение, хотя на самом деле это была SomeSeeminglyUnrelatedFunction функция, встроенная в Main.

Так что, если вы приземлитесь здесь, пожалуйста, подумайте, есть ли у вас похожая проблема. (Я понимаю, что это не может быть прямым ответом на вопрос ОП, но тем не менее хотел бы поделиться, поскольку это может помочь будущему посетителю.)

2 голосов
/ 17 февраля 2010

Не уверен насчет нуля, но почему вы не используете:

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

Редактировать: что касается нулевых значений. У вас есть несколько потоков, обращающихся к этому IDictionary? Коррупция возможна, если вы не в безопасности. Смотрите этот пост для примера коррупции в

Queue<T>

класс. Как изменить коллекцию очередей в цикле?

2 голосов
/ 17 февраля 2010

Это исключение происходит, если ключом словаря является null. Поскольку встроенный класс Dictionary не поддерживает такие ключи, возможно, вы используете собственный класс, совместимый с IDictionary, который позволяет null.

1 голос
/ 17 февраля 2010

Возможно ли, что другой поток влияет на направление, передаваемое в Convert?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...