C#.NET中泛型接口中的协变性

3

我有一组接口,看起来像这样:

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’。”
所以我的问题是:既然 Container 已经通过协变实现了 IBaseContainer,难道不应该也实现 IBaseContainer 吗?还是我理解错了什么?

如果Container<Item>已经是IDerivedContainer的具体实现,为什么还需要实现IMyContainer呢?你的IMyContainer接口将强制你使用public IBaseItem Item { get; },这将隐藏public IDerivedItem Item { get; } - Yuval Itzchakov
IMyContainer 将是一个公共接口,将在解决方案的其他部分中使用,并且它将在以后拥有其他属性。除此之外,我的 IDerivedItem 将具有只有某些类型的开发人员才能访问的属性。 - J. Edmond
1
那么你需要解决在同一个具体实现中有两个“Item”对象的问题。 - Yuval Itzchakov
1个回答

0

你的声明实际上需要 两个 Item 属性,像这样:

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

原因是实现 IBaseContainer<IBaseItem> 会导致一个 IBaseItem Item { get; } 属性,而继承 Container<Item> 则会导致实现 IDerivedContainer<Item>,从而意味着 IBaseContainer<Item> 含有一个 Item Item { get; } 属性。自然地,IBaseItem ItemItem Item 是两个不同的东西。

从你的设计中并不清楚为什么要有一个单独的 IMyContainer,这导致了这个问题。尝试完全删除 IMyContainer,因为乍一看它是对 IBaseContainer 实现的不必要重复。


我明白了,但是使用协变无法改变这一点吗?我的意思是,既然IBaseContainer<Item>通过协变可以成为IBaseContainer<IBaseItem>,那么理论上至少应该是正确的,不是吗? - J. Edmond
@J.Edmond 这并不是关于方差的问题。这些声明只是导致两个不同接口的实现:IBaseContainer<Item>IBaseContainer<IBaseItem> - Ondrej Tucny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接