Вопрос по c#, interface, casting, generics – Вложенные интерфейсы: приведение IDictionary <TKey, IList <TValue >> к IDictionary <TKey, IEnumerable <TValue >>?

1

Я думаю, довольно просто разыгратьIDictionary<TKey, IList<TValue>> возражать противIDictionary<TKey, IEnumerable<TValue>>, но

<code>var val = (IDictionary<TKey, IEnumerable<TValue>>)Value;
</code>

бросаетSystem.InvalidCastException, а также

<code>var val = Value as IDictionary<TKey, IEnumerable<TValue>>;
</code>

маркиval ноль. Как правильно разыграть это?

Ваш Ответ

2   ответа
7

IDictionary<TKey, IList<TValue>> object to an IDictionary<TKey, IEnumerable<TValue>>

Точно нет. Это не будет типобезопасным. Вот пример того, почему нет:

// This is fine...
IDictionary<string, IList<int>> dictionary = new Dictionary<string, IList<int>>();

// Suppose this were valid...
IDictionary<string, IEnumerable<int>> badDictionary = dictionary;

// LinkedList<T> doesn't implement IList<T>
badDictionary["foo"] = new LinkedList<int>();

// What should happen now?
IList<int> bang = dictionary["foo"];

Как вы можете видеть, это вызовет проблемы - мы пытаемся получитьLinkedList<int> когда мы ожидаем, что все значения для реализацииIList<int>, Суть обобщения заключается в том, чтобы быть безопасным с точки зрения типов - так какую линию вы ожидаете потерпеть неудачу? Первая, третья и четвертая строки выглядят довольно четко для меня, поэтому втораяonly тот, который может не скомпилироваться, и это делает ...

Сейчас вsome случаев, это можно сделать безопасно. Например, вы можете конвертировать (в C # 4) изIEnumerable<string> вIEnumerable<object> так какIEnumerable<T> только используетT в & quot; выводе & quot; позиции.

УвидетьMSDN Больше подробностей.

РЕДАКТИРОВАТЬ: просто чтобы уточнить - легко создатьnew словарь с копией существующих пар ключ / значение, например, используя ссылку:

var copy = original.ToDictionary<TKey, IEnumerable<TValue>>(pair => pair.Key,
                                                            pair => pair.Value);

Вам просто нужно знать, что теперь у вас есть два отдельных словаря.

Ну, это не имеет смысла для меня.IEnumerable<> не наследуется отIList<>все наоборот, так что, очевидно, это неправильно. Вы можете сыграть роль предка, а не потомка, верно? Так как же это лишает законной силы уныние? Jeremy Holovacs
@JeremyHolovacs: мой пример пытался сделатьexactly что вы утверждали, что хотите сделать: конвертироватьIDictionary<TKey, IList<TValue>> кIDictionary<TKey, IEnumerable<TValue>>, Если это не то, что вы хотели сделать, вам следует уточнить свой вопрос.
Последняя строка, кажется, не делает то же самое вообще; там вы, кажется, пытаетесь преобразоватьIEnumerable<int> дляIList<int>и это, очевидно, неправильно для меня. ПреобразованиеIList<int> дляIEnumerable<int> кажется, это должно быть совершенно законно, так какIList наследует отIEnumerable. Jeremy Holovacs
@JeremyHolovacs: Нет, потому что последняя строка извлекается изdictionaryнеbadDictionaryи типdictionary являетсяIDictionary<string, IList<int>>, Прочитайте это внимательно. Все дело в том, что последняя строка (или третья) должна была потерпеть неудачу вexecution time несмотря на то, что полностью действителен вcompile время, и это не хорошо.
@JeremyHolovacs: имейте в виду, что словари являются ссылочными типами, и это "приведение" не означает «преобразование» Вот. После предложенного вами приведения обе переменные будут указывать на один и тот же единственный словарь (если приведение возможно). Приведение просто говорит компилятору: «Обработайте A, как если бы это был B». Может быть, это поможет вам лучше понять точку зрения Джона Скита.
0

но я подумал, что я выброшу это как дополнение к ответу Джона.

Если все, что вам нужно, это словарьvaluesбез ссылки на их ключи вы можете сделать это:

IDictionary<TKey, IList<TValue>> dictionary = Whatever();
var values = (IEnumerable<IEnumerable<TValue>>)dictionary.Values;

Чтобы это работало, вы должны использовать C # 4.0 или новее, а TValue должен быть ограничен, чтобы быть ссылочным типом. Вот код, слегка переработанный и с комментариями для объяснения:

IDictionary<TKey, IList<TValue>> dictionary = Whatever();

//Values returns an ICollection<IList<TValue>>
ICollection<IList<TValue>> temp1 = dictionary.Values;

//ICollection<T> inherits from IEnumerable<T>
IEnumerable<IList<TValue>> temp2 = temp1;

//IEnumerable<T> is covariant
//There is an implicit reference conversion between IList<T> and IEnumerable<T>
//So there is an implicit reference conversion between IEnumerable<IList<T>>
//and IEnumerable<IEnumerable<T>>
IEnumerable<IEnumerable<TValue>> values = temp2;

Похожие вопросы