Как правильно реализовать конкретный класс, который наследует интерфейс с List <AnotherInterface> [duplicate]

2

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

public interface IDataDictionary
{
    List<IDataDictionaryItem> DictionaryItems { get; set; }
}

И элементы словаря как:

public interface IDataDictionaryItem
{
    Guid Guild { get; set; }

    int SequenceId { get; set; }

    string Title { get; set; }

    string Value { get; set; }

    string Description { get; set; }

    string Language { get; set; }

} 

Когда я пытаюсь реализовать это в конкретном классе, например:

public class HairColorDictionary : IDataDictionary
{
    public List<HairColor> DictionaryItems { get; set; }
}

С пунктами конкретной реализации:

public class HairColor : IDataDictionaryItem
{
    public Guid Guild { get; set; }
    public int SequenceId { get; set; }
    public string Title { get; set; }
    public string Value { get; set; }
    public string Description { get; set; }
    public string Language { get; set; }
}

Я получаю сообщение об ошибке ниже, и я не могу обернуться вокруг него. Может кто-нибудь, пожалуйста, просветите меня, где это пошло не так.

Сообщение об ошибке:

Ошибка CS0738 "HairColorDictionary" не реализует элемент интерфейса "IDataDictionary.DictionaryItems". "HairColorDictionary.DictionaryItems" не может реализовать "IDataDictionary.DictionaryItems", поскольку у него нет соответствующего возвращаемого типа "List".

  • 1
    Существует определенное сходство с указанным возможным дубликатом, но это определенно обеспечило лучшее понимание проблемы / решения с другой точки зрения.
Теги:

2 ответа

2
Лучший ответ

Я понимаю, к чему вы стремитесь, и причина, по которой он не работает, заключается в том, что интерфейс определил коллекцию, которая не является специфической (этот интерфейс может быть реализован), но вы пытаетесь реализовать этот элемент интерфейса в определенном путь.

Если вы действительно должны это сделать, вы можете сделать это с помощью дженериков. Вот обновленные биты:

public interface IDataDictionary<T> where T : IDataDictionaryItem
{
    List<T> DictionaryItems { get; set; }
}

public class HairColorDictionary : IDataDictionary<HairColor>
{
    public List<HairColor> DictionaryItems { get; set; }
}

T позволяет вам использовать что угодно, а часть where T:... накладывает на это ограничение.

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

  • 1
    Это фактически решило мою проблему, а также обеспечило лучшее понимание работы наследования интерфейса. Спасибо!
1

В вашей реализации HairColorDictionary is-a IDataDictionary. Так что я мог бы сделать что-то плохое, как:

IDataDictionary d = new HairColorDictionary();
d.DictionaryItems.add(blah);

Здесь метод add ожидает что-то типа IDataDictionaryItem и не обязательно HairColor потому что d это просто IDataDictionary а не HairColorDictionary ! Так что я мог бы сделать что-то вроде

class SkinColor : IDataDictionaryItem { ... }
IDataDictionaryItem s = new SkinColor();
d.DictionaryItems.add(s);

Вопрос в том, действительно ли это последнее утверждение или нет? Он должен быть действительным, потому что add ожидает IDataDictionaryItem который SkinColor правильно реализует. Но тогда это не должно быть действительным, потому что фактический public List<HairColor> DictionaryItems допускает только HairColor а не SkinColor s !!!

Чтобы устранить эту путаницу и обеспечить строгую безопасность типов, вы должны следовать правилам ковариации и контравариантности. Или вы можете продолжить с @TheMuffinMan хорошим ответом.

  • 0
    Да, согласился Прежде чем задать вопрос, я не осознавал такую возможность. Из-за непонимания конечно. Я получил ценный урок с этим. И спасибо за то, что вы также добавили к нему немного слова!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню