如果我正确理解了您描述的.NET接口继承链,那么您是错误的。这是一个容易犯的错误,因为文档让它看起来像那样。IList<T>
仅明确从ICollection<T>
继承;它不会从ICollection<T>
、IEnumerable<T>
和IEnumerable
继承。这是来自参考源代码的实际定义:
public interface IList<T> : ICollection<T>
同样适用于
ICollection<T>
,它只继承自
IEnumerable<T>
。在编译期间,接口的继承树被展平和去重。因此,继承
ICollection
的接口不仅继承该接口,而且还继承
IEnumerable
本身。
视觉示例:
IMine : ICollection<T> != IMine : (ICollection<T>:(IEnumerable<T>:IEnumerable))
相反,它看起来是这样编译的:
IMine: ICollection<T>, IEnumerable<T>, IEnumerable
这就解释了为什么你得出了你的结论。
关于多接口继承的真实世界示例,请看 IQueryable
和 IOrderedQueryable
的示例。这些接口的实际源声明如下:
public interface IQueryable<out T> : IEnumerable<T>, IQueryable {}
public interface IOrderedQueryable<out T> : IQueryable<T>, IOrderedQueryable {}
IQueryable
需要有一个契约来指定您可以迭代每个元素,但也需要具备与简单的 IEnumerable
区分的能力。它独自一人,而不是所有的 IEnumerable
类型,可以在 IQueryProvider
和静态的 Queryable
类中使用。
另一个有趣的在System.Collections.Concurrent
命名空间中。
public interface IProducerConsumerCollection<T> : IEnumerable<T>, ICollection
这很有趣,因为它继承了非泛型的ICollection
和IEnumerable<T>
,它们都继承自IEnumerable
。当然,这不是问题,但这是另一个很好的例子。如果IProducerConsumerCollection<T>
继承自其非泛型对应物ICollection<T>
而不是ICollection
,我相信它不会明确地继承IEnumerable<T>
。它具有在ICollection
中定义的大小、(旧)枚举器和同步方法行为,以及在IEnumerable<T>
中定义的通用枚举行为。
这里有两个例子。我发现还有更多,但我认为这些可能已经足够了。