Почему я не могу добавить null в качестве значения при использовании ConcurrentDictionary?

Рассмотрим следующий код:

// holds the actual values
        private volatile ConcurrentDictionary<string, Object> values;

        public object this[string key] {
            get {     
                // exception is thrown on this line          
                return values.GetOrAdd(key, null);                
            }
            set {
                values.AddOrUpdate(key, value, (k, v) => value);                
            }
        }

Что я хочу сделать, так это просто создать запись в словаре, если она еще не существует; он не должен иметь значения, пока что-то явно не установит его. Я получаю это исключение, хотя:

An unhandled exception of type 'System.ArgumentNullException' occurred in mscorlib.dll

Additional information: Value cannot be null.

В документации указано, что ключ не может быть нулевым, что имеет смысл. почему я получаю это исключение за значение? Я не понимаю этот метод?


person dmarra    schedule 21.06.2016    source источник
comment
@sstan Дополнительная информация: Value не может быть нулевым.   -  person Dovydas Šopa    schedule 21.06.2016
comment
@sstan Вот что написал ОП.   -  person Dovydas Šopa    schedule 21.06.2016
comment
Поскольку вся цель словаря состоит в том, чтобы разрешить использование ключа для поиска значения, нет смысла разрешать нулевые значения. Если у ключа нет значения, ему не место в словаре, точно так же, как в IRL слово не принадлежит словарю, пока у него нет определения. Вы ведь не находите в словаре неопределенные слова, не так ли?   -  person Ken White    schedule 21.06.2016
comment
@KenWhite null полностью разрешено в качестве словарного значения. Смотрите ответ Алексея.   -  person piedar    schedule 21.06.2016
comment
@piedar: я не имел в виду, что это строго запрещено. Я имел в виду то, что сказал; нет смысла разрешать это, потому что словарь с ключом и без значения бесполезен по определению.   -  person Ken White    schedule 21.06.2016
comment
@KenWhite Иногда вы хотите, чтобы ключ был готов и ждал его значения. При написании словаря реального мира есть короткий промежуток времени, когда у вас есть слово без определения. Он ПОЛУЧИТ один, но это заполнитель.   -  person dmarra    schedule 21.06.2016


Ответы (1)


В итоге код вызывает другой метод GetOrAdd, принимает Func в качестве аргумента (и явно требуется, чтобы он не был нулевым - «key or valueFactory is null»).

public TValue GetOrAdd(TKey key,Func<TKey, TValue> valueFactory)...

Fix: указать тип явно:

 values.GetOrAdd("test", (Object)null);

Почему: C# всегда пытается найти более конкретное соответствие, а Func<TKey, TValue> более конкретное, чем Object, поэтому выбирается переопределение.

person Alexei Levenkov    schedule 21.06.2016
comment
Если бы OP использовал более конкретный тип для TValue, компилятор помог бы ему, предоставив ему сообщение об ошибке call is ambiguous. - person sstan; 21.06.2016
comment
Спасибо! это имеет большой смысл. приведение к объекту облегчает мою насущную проблему. - person dmarra; 21.06.2016