C#可以隐藏继承的接口吗?

时间:2014-08-12 21:23:03

标签: c# .net generics inheritance interface

我有一组看起来像这样的接口和类:

public interface IItem
{
    // interface members
}
public class Item<T> : IItem
{
    // class members, and IItem implementation
}
public interface IItemCollection : IEnumerable<IItem>
{
    // This should be enumerable over all the IItems
}
// We cannot implement both IItemCollection and IEnumerable<TItem> at
// the same time, so we need a go between class to implement the
// IEnumerable<IItem> interface explicitly:
public abstract class ItemCollectionBase : IItemCollection
{
    protected abstract IEnumerator<IItem> GetItems();
    IEnumerator<IItem> IEnumerable<IItem>.GetEnumerator() { return GetItems(); }
    IEnumerator IEnumerable.GetEnumerator() { return GetItems(); }
}

public class ItemCollection<TKey, TItem> : ItemCollectionBase, IEnumerable<TItem>
    where TItem : class,IItem,new()
{
    private Dictionary<TKey, TItem> dictionary;
    protected override GetItems() { return dictionary.Values; }
    public IEnumerator<TItem> GetEnumerator() { return dictionary.Values; }
}

我遇到的问题是当我尝试在我的ItemCollection上使用Linq时,它会因为有两个IEnumerable接口而感到困惑。

我收到以下错误消息:

无法从用法推断出方法'System.Linq.Enumerable.Where(...)的类型参数。尝试明确指定类型参数。

有没有办法隐藏“更原始的”IEnumerable&lt; IItem&gt;界面因此它将始终选择IEnumerable&lt; TItem&gt;当处理ItemCollection&lt;,&gt;时,仍然提供IEnumerable&lt; IItem&gt;处理IItemCollection接口时的接口?


(正如我即将发布的那样,我意识到有一种解决方法,就像这样实现它:

public interface IItemCollection
{
    IEnumerable<IItem> Items { get; }
}

但我仍然想知道是否有隐藏界面的方法。)

2 个答案:

答案 0 :(得分:1)

也许你可以用一点点的构图而不是继承来实现你想要的东西:

public interface IItem
{
    // interface members
}
public class Item<T> : IItem
{
    // class members, and IItem implementation
}
public interface IItemCollection
{
    IEnumerable<IItem> GetItems();
}    
public class ItemCollection<TKey, TItem> : IItemCollection, IEnumerable<TItem>
    where TItem : class,IItem,new()
{
    private Dictionary<TKey, TItem> dictionary;
    public IEnumerator<TItem> GetEnumerator() { return dictionary.Values; }
    public IEnumerable<IItem> GetItems() { return dictionary.Values.Cast<IItem>(); }
}

我们可以更改IItemCollection,以便返回IEnumerable<IItem>而不是IEnumerable<IItem>。现在,您的具体类可以实现所有接口,并且您不需要抽象类。

答案 1 :(得分:0)

我认为你正在走向一个违反Liskov substitution principle的聪明设计(如果有的话)

  

使用指针或对基类的引用的函数必须能够   在不知情的情况下使用派生类的对象。

作为一个比我聪明的人曾经说过“不要让你的设计变得聪明,亲吻。”