简体   繁体   English

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

[英]C# can you hide an inherited interface?

I have a set of interfaces and classes that look something like this: 我有一组接口和类看起来像这样:

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; }
}

The problem I run into is when I try use Linq on my ItemCollection, it gets confused because there are two IEnumerable interfaces. 我遇到的问题是当我尝试在我的ItemCollection上使用Linq时,它会因为有两个IEnumerable接口而感到困惑。

I get the following error message: 我收到以下错误消息:

The type arguments for method 'System.Linq.Enumerable.Where(...) cannot be inferred from the usage. 无法从用法推断出方法'System.Linq.Enumerable.Where(...)的类型参数。 Try specifying the type arguments explicitly. 尝试显式指定类型参数。

Is there any way to hide the "more primitive" IEnumerable<IItem> interface so it will always choose the IEnumerable<TItem> when dealing with the ItemCollection<,>, but still provide the IEnumerable<IItem> interface when dealing with IItemCollection interface? 有没有办法隐藏“更原始”的IEnumerable <IItem>接口,所以它在处理ItemCollection <,>时总会选择IEnumerable <TItem>,但在处理IItemCollection接口时仍然提供IEnumerable <IItem>接口?


(As I'm about to post this, I realized that there's a workaround, to implement it like this: (正如我即将发布的那样,我意识到有一种解决方法,就像这样实现它:

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

But I still want to know if there's a way to hide an interface.) 但是我仍然想知道是否有隐藏界面的方法。)

Perhaps you could achieve what you want with a little bit of composition instead of inheritance: 也许你可以通过一点点组合而不是继承来实现你想要的东西:

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>(); }
}

We can change IItemCollection so that it returns an IEnumerable<IItem> instead of implementing IEnumerable<IItem> . 我们可以更改IItemCollection ,使其返回IEnumerable<IItem>而不是实现IEnumerable<IItem> Now your concrete class can implement all interfaces and you don't need abstract classes. 现在,您的具体类可以实现所有接口,而您不需要抽象类。

I think you are heading to a clever design (if there is one) which violates Liskov substitution principle 我认为你正在寻找一个违反Liskov替代原则的聪明设计(如果有的话)

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it. 使用指针或对基类的引用的函数必须能够在不知道它的情况下使用派生类的对象。

As someone smarter than me once said "don't make your design clever, KISS." 作为一个比我聪明的人曾经说过“不要让你的设计变得聪明,亲吻。”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM