Возврат подтипа IEnumerable в словаре невозможен

Почему это проблема в C#?

public Dictionary<string, IEnumerable<object>> GetProducts() {
    return new Dictionary<string, IList<object>>();
}

person Jakob Rasmussen    schedule 03.05.2013    source источник
comment
Джейкоб, пожалуйста, в будущем более подробно описывайте свою проблему. Похоже, на этот раз на ваш вопрос можно было ответить, но подробное объяснение проблемы полезно для тех, кто пытается ответить на ваш вопрос.   -  person tnw    schedule 03.05.2013


Ответы (2)


Это невозможно, потому что будет создан словарь со значением IList<object>.

Итак, если вы позвоните:

IEnumerable<object> values = someOtherObjectCollectionPerhapseSomethingFromLinq;
Dictionary<string, IEnumerable<object>> products = GetProducts();
products.Add("MyKey", values);

Ваш возвращаемый словарь примет IEnumerable<object>, но нижележащий словарь не примет его, поскольку его значения ДОЛЖНЫ БЫТЬ типа IList<object>, что в данном случае не так.

person Martin Mulder    schedule 03.05.2013

Вы не можете вернуть это:

new Dictionary<string, IList<object>>();

.. но вы можете вернуть это:

new Dictionary<string, IEnumerable<object>>();

.. или измените тип возврата:

public Dictionary<string, IList<object>> GetProducts(){ ... }

Часть рассуждений об этом:

Представьте, что вы можете получить возвращаемый словарь как Dictionary<string, IEnumerable<object>>, но со значениями как List<object> вместо IEnumerable<object> (где List — это более конкретный тип IEnumerable).

Если вы затем попытаетесь добавить к нему новый IEnumerable<object>, это будет недопустимой операцией, так как ваши элементы на самом деле относятся не к типу IEnumerable<object>, а скорее к типу List<object>.

Причина, по которой это запрещено, заключается в том, что элемент типа List<object> может содержать (и содержит) методы, которых нет в IEnumerable<object>.

Представьте, что вы добавляете элемент типа IEnumerable<object> в Dictionary<string, List<object>>. Это означает, что вы можете вызывать List<object>-специфический метод для каждого элемента, пока не достигнете первого IEnumerable<object>-элемента, где этот метод не будет определен, и поэтому сгенерировать исключение.

Ваш исходный код вызывает ошибку времени компиляции, чтобы вы никогда не сталкивались с такими проблемами.

Я сам спросил связанный вопрос не так давно, что может помочь лучше понять это.

person Kjartan    schedule 03.05.2013