Как получить пары ключ-значение определенного типа только из словаря

У меня есть IDictionary (не общий, поэтому я имею дело с object здесь), и я хотел бы получить от него только элементы в этом IDictionary, которые соответствуют определенному типу ключа K и определенному типу значения V. Существует миллиард способы сделать это, но самый элегантный способ, который я нашел, выглядит следующим образом:

Dictionary<K, V> dict = myIDictionary.OfType<KeyValuePair<K, V>>();

Это компилируется нормально, поэтому я предполагаю, что этот метод МОЖЕТ работать для словаря (он объявлен IEnumerable), но результирующий словарь пуст, хотя там определенно есть KVP, соответствующие этим условиям. Очевидно, я предполагал, что KeyValuePair<K, V> - это ожидаемый формат, поскольку именно он используется при перечислении по словарю, но это что-то другое? Есть что-то, что мне не хватает?


person Maltor    schedule 06.09.2013    source источник
comment
Каков тип среды выполнения словаря?   -  person Servy    schedule 06.09.2013
comment
Я гость, тип словаря (орудия IDictionary) можно найти в System.Collections.Specialized, там есть ListDictionary, HybridDictionary и OrderedDictionary.   -  person King King    schedule 06.09.2013


Ответы (2)


Необщий тип IDictionary не использует тип KeyValue<T,U>, поэтому у вас никогда не будет совпадений.

Вам нужно будет проанализировать элементы DictionaryEntry и преобразовать их:

Dictionary<K,V> dict = myIDictionary
                          .Cast<DictionaryEntry>()
                          .Where(de => de.Key is K && de.Value is V)
                          .ToDictionary(de => (K)de.Key, de => (V)de.Value);
person Reed Copsey    schedule 06.09.2013
comment
Спасибо, я подумал, что это будет более сложный запрос LINQ. Тогда просто любопытно: что может быть возможным вариантом использования OfType с IDictionary? Есть ли какой-нибудь сценарий, когда он не вернет ни весь набор данных, ни ничего? - person Maltor; 06.09.2013
comment
@Maltor Не совсем так - перечислителем всегда будет DictionaryEntry, поскольку он не является универсальным. Однако это полезно для других неуниверсальных коллекций. - person Reed Copsey; 06.09.2013

Функция OfType фильтрует список на основе указанного типа... но у вас нет ничего типа KeyValuePair<K,V> в вашей базе IDictionary. У вас есть только тот тип, который содержит необобщенный объект IDictionary (на данный момент я не уверен - может быть, DictionaryEntry?). Даже если он «совпадает» по универсальным типам пары, на самом деле это не один и тот же внешний тип.

Так что эта функция не будет делать то, что вы ищете. Вам нужно что-то сделать с оператором Where. Что-то типа:

var dict = myIDictionary.Where(e => e.Key is typeof(K) && e.value is typeof(V))

хотя это прямой псевдокод, а не реальный синтаксис.

Редактировать: похоже, что Рид довольно хорошо изложил полное решение.

person Tim    schedule 06.09.2013