Почему мой код не поддерживает Co-вариант интерфейса? - PullRequest
0 голосов
/ 08 февраля 2012

По словам рефлектора, ExpandoObject Реализует IDictionary<string, object>

enter image description here

Как же у меня есть этот код, который я не понимаю, почему здесь не работает согласованность интерфейса

enter image description here

Из того, что я прочитал - это предполагает работу:

enter image description here

Ответы [ 2 ]

3 голосов
/ 08 февраля 2012

Здесь три вещи не так:

  • IDictionary<TKey, TValue> инвариантен в обоих параметрах своего типа
  • Общая дисперсия не работает для типов значений (int здесь)
  • Если бы это было ковариантным, вы бы попытались использовать его неправильно: вы на самом деле пытаетесь использовать противоположность

Вы должны игнорировать часть dynamic здесь - это красная сельдь. Попробуйте выработать какой-нибудь код, который, как вы ожидаете, будет работать, который не использует dynamic. Вот пример того, почему IDictionary<,> является инвариантом:

// Suppose it were covariant in value...
Dictionary<string, string> stringToString = new Dictionary<string, string>();
IDictionary<string, object> stringToObject = stringToString;
stringToObject["foo"] = new MemoryStream();
string value = stringToString["foo"]; // Um?

// Suppose it were contravariant in value...
Dictionary<string, object> stringToObject = new Dictionary<string, object>();
IDictionary<string, string> stringToString = stringToString;
stringToObject["foo"] = new MemoryStream();
string value = stringToString["foo"]; // Um?
1 голос
/ 08 февраля 2012
  1. IDictionary<TKey,TValue> не поддерживает никаких отклонений.
    Представьте, что произойдет, если вы сможете конвертировать IDictionary<string,object> в IDictionary<string,int>:
    Теперь ваш интерфейс гарантирует , что каждое возвращаемое им значение является int. Но поскольку вы можете добавлять к нему произвольные объекты, это не может гарантировать такую ​​гарантию.
  2. Даже интерфейсы, которые поддерживают дисперсию, поддерживают ее только между ссылочными типами. int не является ссылочным типом.
  3. Эта проблема не связана с динамической. Вы не можете преобразовать класс, который реализует только IDictionary<string,object> в IDictionary<string,int>. Неважно, используете ли вы статическое или динамическое приведение. Он просто не реализует этот интерфейс.
...