Ковариантность C # в классах, реализующих общий интерфейс - PullRequest
0 голосов
/ 13 февраля 2012

WPF-программа, которую я пишу на C #, имеет на интерфейсе следующий интерфейс:

public interface CatalogMenu<T> : CatalogItem where T : CatalogItem
{
    void AddCatalogItem(T toAdd);
    void RemoveCatalogItem(T toRemove);

    List<T> AvailableCatalogItems { get; }
}

У меня есть три класса, которые реализуют интерфейс, каждый с различным T. Проблема в том, что я хочу создать List<CatalogMenu<CatalogItem>> для привязки к ListView, но это свойство в View-Model не компилируется .. . (thing1, thing2 и thing3 все реализуют интерфейс с другим T)

public List<CatalogMenu<CatalogItem>> MenuCategories
    {
        get
        {
            return new List<CatalogMenu<CatalogItem>>(){
                ModuleCatalog.thing1, 
                ModuleCatalog.thing2, 
                ModuleCatalog.thing3 
            };
        }
    }

Как бы мне этого ни хотелось, компилятор не позволит мне рассматривать «классы, реализующие CatalogMenu<T>, где T - это CatalogEntity», как «CatalogMenu<CatalogItem>». Я хочу представить каждый класс, реализующий интерфейс, пользователю через общий интерфейс.

Если я пропущу какие-либо подробности, будь со мной немного терпеливым; спагетти моей головы после прочтения о ковариации в течение последних 30 минут в попытке выяснить, как это исправить.

1 Ответ

2 голосов
/ 13 февраля 2012

.Net не поддерживает ковариантные классы .

Если вы добавите ICatalogMenu<out T>, вы сможете привести любое CatalogMenu к ICatalogMenu<CatalogItem> и поместить его в List<ICatalogMenu<CatalogItem>>

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

...