Реализация .Net интерфейсов (C #) - PullRequest
3 голосов
/ 08 апреля 2011

Наверное, простой вопрос.

У меня есть интерфейс (MyInterface), который определяет свойство следующим образом:

IList<IMenuItem> MenuCollection { get; }

А класс, реализующий MyInterface

public class MyClass : MyInterface
{
    public ObservableCollection<MenuItemBase> MenuCollection 
    {
       get
       {
           ...
       }
    }
    ....
}

Из того, что я прочитал, ObservableCollection наследует коллекцию, которая является IList, и у меня есть класс MenuItemBase, который реализует IMenuItem - разве это не удовлетворит интерфейс?

Я полагаю, интерфейсы должны быть реализованы явно?

Я тоже пробовал это:

public class MyClass : MyInterface
{
    public IList<IMenuItem> MenuCollection MenuCollection 
    {
       get
       {
           if(_menuCollection == null)
              _menuCollection = new ObservableCollection<MenuItemBase>();
           return _menuCollection as IList<IMenuItem>;
       }
    }
    private ObservableCollection<MenuItemBase> _menuCollection;
}

Похоже на обходной путь (и я столкнулся с несколькими проблемами, говоря, что MenuCollection не был создан), чтобы интерфейс был удовлетворен ... Есть ли лучший способ реализовать IInterface1<IInterface2> объекты?

Причина, по которой я нуждаюсь в такого рода абстракции, заключается в том, что я создаю приложение призмы / единства и хочу максимально отделить модель представления меню от ленточного интерфейса, отображающего меню.

Ответы [ 3 ]

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

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

То есть, если Animal является базовым типом Giraffe, то интерфейсный метод, который возвращает Animal, или виртуальный метод, который возвращает Animal, может быть реализован / специализирован методом, который возвращает Giraffe. Поскольку каждый Жираф - Животное, контракт выполнен.

C # не поддерживает ковариацию возвращаемого типа; в этом отношении также не делает CLR. Некоторые языки поддерживают ковариацию возвращаемого типа; С ++ к примеру приходит на ум. (Реализация C ++ / CLI делает некоторые хитрые трюки, чтобы обойти ограничения CLR.) Тип возвращаемого значения реализованного метода интерфейса, тип свойства и т. Д. Все должны совпадать с точно в C #.

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

Это не имеет ничего общего с общей дисперсией

Существует несколько ответов, говорящих о общей дисперсии.Это не имеет ничего общего с примером.Если вы попытаетесь реализовать свойство, определенное как IList с ArrayList (без обобщения), вы увидите, что это все еще невозможно сделать.

Правильный ответ

Этоэто связано с тем, что если бы вы могли реализовать MenuCollection как свойство некоторого типа, реализующего IList<T> (или производного от него, если бы он не был указан как интерфейс), то это было бы возможно:

public interface MyInterface
{
    IList<IMenuItem> MenuCollection { get; set }
}

public class MyClass : MyInterface
{
    // WARNING: Does not count as implementing the interface -- with good reason
    public ObservableCollection<MenuItemBase> MenuCollection { get; set; }
}

var myClass = new MyClass();
var classAsInterface = (MyInterface) myClass; // This is OK of course

classAsInterface.MenuCollection = new List<MenuItemBase>(); // OOPS!!

В этой последней строке вы присвоили List<MenuItemBase> (что нормально, насколько может сказать MyInterface, поскольку MyInterface.MenuCollection имеет тип IList<MenuItemBase>) свойству типа ObservableCollection<MenuItemBase>.

Конечно, это недопустимо, поскольку List<MenuItemBase> явно не является производным от ObservableCollection<MenuItemBase>.Но было бы возможно, если бы вы могли реализовать такой интерфейс.

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

List<T> и IList<T> не поддерживают ковариацию .

См. Этот вопрос: Вопрос о C # ковариации

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...