2015-11-22 5 views
3

у меня есть набор интерфейсов, который выглядит следующим образом:ковариации в общих интерфейсов в C# .NET

interface IBaseItem { } 

interface IDerivedItem : IBaseItem { } 

class Item : IDerivedItem { } 

interface IBaseContainer<out TItem> 
    where TItem : IBaseItem 
{ 
    TItem Item { get; } 
} 

interface IDerivedContainer<out TItem> : IBaseContainer<TItem> 
    where TItem : IDerivedItem 
{ } 

class Container<TItem> : IDerivedContainer<TItem> 
    where TItem : IDerivedItem 
{ 
    public TItem Item 
    { 
     get { return default(TItem); } 
    } 
} 

interface IMyContainer : IBaseContainer<IBaseItem> { } 

class MyContainer : Container<Item>, IMyContainer { } 

И когда я пытаюсь скомпилировать, что компилятор говорит: «MyContainer» не реализует элемент интерфейса ' IBaseContainer.Item. «Container.Item» не может реализовать «IBaseContainer.Item», потому что у него нет соответствующего типа возврата «IBaseItem».

Так что мой вопрос: не должен ли контейнер контейнера IBaseContainer, поскольку он реализует IBaseContainer, что эквивалентно IBaseContainer по ковариации? Или у меня что-то не так?

+0

Зачем вам нужно реализовать 'IMyContainer', если' Container 'уже является конкретной реализацией' IDerivedContainer'? Интерфейс 'IMyContainer' заставит вас использовать' public IBaseItem Item {get; } ', который скроет' public IDerivedItem Item {get; } ' –

+0

' IMyContainer' будет публичным интерфейсом, который будет использоваться в другой части решений, и позже он будет иметь другие свойства. И, кроме того, мой IDerivedItem будет иметь свойства, которые должны иметь только некоторые разработчики. –

+1

Затем вам нужно решить проблему наличия двух объектов «Предмет» в одной и той же конкретной реализации. –

ответ

0

Ваши заявления фактически требуют дваItem свойства, например:

class MyContainer : Container<Item>, IMyContainer 
{ 
    public new IBaseItem Item { get { … } } 
} 

Причина реализации IBaseContainer<IBaseItem> приводит к IBaseItem Item { get; } собственности, в то время как iheriting Container<Item>, что, в свою очередь, приводит к реализации IDerivedContainer<Item> и, следовательно, IBaseContainer<Item> подразумевает недвижимость Item Item { get; }. В принципе, IBaseItem Item и Item Item - это две разные вещи.

Непонятно из вашего дизайна, почему вам нужен отдельный IMyContainer, который приводит к этой проблеме. Попробуйте удалить IMyContainer, потому что на первых взглядах это нежелательное дублирование IBaseContainer.

+0

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

+0

@ J.Edmond Это не совсем о разнице. Объявления просто приводят к реализации двух * отдельных * интерфейсов: 'IBaseContainer ' и' IBaseContainer '. –

Смежные вопросы