Приведение общего словаря, содержащего общий словарь - PullRequest
8 голосов
/ 12 апреля 2011

у меня есть:

var someConcreteInstance = new Dictionary<string, Dictionary<string, bool>>();

и я хочу привести его к версии интерфейса, т. Е .:

someInterfaceInstance = (IDictionary<string, IDictionary<string, bool>>)someConcreteInstance;

someInterfaceInstance является публичной собственностью:

IDictionary<string, IDictionary<string, bool>> someInterfaceInstance { get; set; }

Это компилируется правильно, но выдает ошибку приведения во время выполнения.

Unable to cast object of type 'System.Collections.Generic.Dictionary`2[System.String,System.Collections.Generic.Dictionary`2[System.String,System.Boolean]]' to type 'System.Collections.Generic.IDictionary`2[System.String,System.Collections.Generic.IDictionary`2[System.String,System.Boolean]]'.

Чего мне не хватает? (Проблемы с вложенным универсальным типом / свойством?)

Ответы [ 3 ]

12 голосов
/ 12 апреля 2011

Остальные ответы верны, но просто чтобы предельно ясно понять, почему это незаконно, рассмотрим следующее:

interface IAnimal {}
class Tiger : IAnimal {}
class Giraffe : IAnimal {}
...
Dictionary<string, Giraffe> d1 = whatever;
IDictionary<string, IAnimal> d2 = d1; // suppose this were legal
d2["blake"] = new Tiger(); // What stops this?

Никакая смертная рука не может помешать вам поместить тигра в словарь животных.Но этот словарь на самом деле должен содержать только жирафов.

По той же причине вы не можете пойти и другим путем:

Dictionary<string, IAnimal> d3 = whatever;
d3["blake"] = new Tiger(); 
IDictionary<string, Giraffe> d4 = d3; // suppose this were legal
Giraffe g = d4["blake"]; // What stops this?

Теперь вы помещаете тигра в переменнуютипа жирафа.

Общая ковариация интерфейса допустима только в C # 4, если компилятор может доказать, что подобные ситуации не могут возникнуть.

4 голосов
/ 12 апреля 2011

IDictionary не поддерживает ковариацию.

Смотри здесь IDictionary в .NET 4 не ковариантен

1 голос
/ 12 апреля 2011

Максимум, что вы сможете сделать, это

IDictionary<string, Dictionary<string, bool>> viaInterface = someConcreteInstance

Причина того, что на ваш внутренний словарь нельзя ссылаться по-другому (или посредством приведения), заключается в том, что хотя Dictionary<string, bool> является IDictionary<string, bool>, не все IDictionary объекты будут Dictionary объектами. Таким образом, получение чистого интерфейса приведёт к тому, что вы, казалось бы, сможете добавить другие пары <string, IDictionary<string, bool>> в исходную коллекцию, когда очевидно, что могут быть нарушения типа для исходного объекта. Поэтому это не поддерживается.

...