C#:传递继承

发布于 2024-10-15 14:54:59 字数 235 浏览 2 评论 0原文

C#中继承是传递关系吗?

我问这个问题是因为我无法理解为什么 IListICollectionIEnumerable 实现为 ICollection; 已经实现了 IEnumerable

感谢您为我澄清这一点。

Is Inheritance a transitive relation in C#?

I am asking because I cannot understand why IList<T> implements ICollection<T> and IEnumerable<T> as ICollection<T> already implements IEnumerable<T>

Thanks for clarifying this for me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

御弟哥哥 2024-10-22 14:54:59

它在所有方面都是传递性的。您用来查看继承层次结构的工具可能有某种特定的显示方式。尽管您可以显式实现接口并从而将其隐藏在智能感知中,但无法取消实现接口。

作为 IList 的作者,您可以自由选择仅从 ICollection 派生,或者从 ICollection 和 IEnumerable 派生。在这种情况下,IEnumerable 是多余的,并且会被 resharper 标记。

It is transitive in all regards. Probably the tool that you use to look at the inheritance hierarchy has a certain way of displaying it. There is no way to unimplement an interface although you can implement it explicitly and thereby hide it from intellisense.

As the author of IList you can freely choose to derive from ICollection only or from ICollection and IEnumerable. IEnumerable would be redundant in this case and flagged by resharper.

千纸鹤 2024-10-22 14:54:59

AFAIK,无论您将 IList 声明为:

public interface IList<T> : ICollection<T>, IEnumerable<T> { ... }

还是简单地声明为:

public interface IList<T> : ICollection<T> { ... }

任何想要实现 IList 的类都必须实现 < em>所有这些接口,即继承的接口。

显然,如果您实现此接口而不实现 IEnumerable/IEnumerable 接口的 GetEnumerator 方法,则会出现编译器错误;这个通过演示的“证明”应该足以告诉您“接口继承”确实是可传递的。


旁注 1. 旁注(有点偏离主题),请考虑您还可以执行以下操作:

class Base
{
    public void Foo() { ... }
}

interface IFoo
{
    void Foo();
}

class Derived : Base, IFoo 
{ }

Derived 实际上并未实现 IFoo;它的基类Base提供了方法Foo,但没有显式实现IFoo本身。

这看起来编译得很好,因为接口所需的所有方法都在那里。 (我现在就将其保留下来,并暂时将确切的技术讨论放在一边。)

我之所以提到这种看似无关的现象,是因为我喜欢以这种方式思考接口继承:您需要实现所需的所有方法通过类声明中指定的接口。因此,当我看到

interface ICollection<T> : IEnumerable<T> { ... }

ICollection继承IEnumerable”而不是说“”时,我可以对自己说,ICollection 还要求所有实现类都实现 IEnumerable。”


旁注 2。用另一个有些相关的轶事来结束这个答案(我保证这将是最后一个):

不久前我观看了视频 .NET Rx 和 IObservable 内部/IObserver 位于第 9 频道的 BCL 中。正如您现在可能看到的,这两个新接口来自 Rx 是通过 .NET 4 引入到 BCL 中的。一个奇怪的事情是,当您通过 observable 订阅一个观察者到一个可观察对象时.Subscribe(observer),你得到的只是一些匿名的IDisposable。为什么?

,他们可以通过定义如下的类型名称“别名”为 IDisposable 指定一个更具描述性的名称(例如 ISubscription):

interface ISubscription : IDisposable {}

正如演讲者在该视频中所解释的那样 ,他们最终决定不这样做。他们认为,一旦从 Subscribe 方法返回 ISubscription,返回值需要进行 Dipose 处理就不再明显了。

因此,这是人们应该牢记的“接口继承”的另一个稍微有问题的方面。

AFAIK, it doesn't truly matter whether you declared IList<T> as:

public interface IList<T> : ICollection<T>, IEnumerable<T> { ... }

or simply as:

public interface IList<T> : ICollection<T> { ... }

Any class that wants to implement IList<T> will have to implement all of these interfaces, i.e. also the inherited ones.

Obviously, if you implemented this interface without implementing the GetEnumerator methods of the IEnumerable/IEnumerable<T> interfaces, you'd get a compiler error; this "proof" by demonstration should be enough to tell you that "interface inheritance" is transitive, indeed.


Sidenote 1. On a side note (and slightly off-topic), consider that you can also do the following:

class Base
{
    public void Foo() { ... }
}

interface IFoo
{
    void Foo();
}

class Derived : Base, IFoo 
{ }

Derived doesn't actually implement IFoo; its base class Base provides method Foo, but doesn't explicitly implement IFoo itself.

This compiles well, seemingly because all the methods that are required by the interfaces are there. (I'll leave it at that and leave the exact technical talk aside for now.)

The reason why I'm mentioning this seemingly unrelated phenomenon is that I like to think of interface inheritance in this way: You need to implement all methods required by the interfaces specified in the class declaration. So when I see

interface ICollection<T> : IEnumerable<T> { ... }

instead of saying, "ICollection<T> inherits IEnumerable<T>", I could say to myself, "ICollection<T> requires of all implementing classes that they implement IEnumerable<T>, also."


Sidenote 2. To conclude this answer with yet another somewhat related anecdote (I promise it'll be the last one):

Some time ago I watched the video Inside .NET Rx and IObservable/IObserver in the BCL on Channel 9. As you might now, those two new interfaces, coming from Rx, were introduced into the BCL with .NET 4. One peculiar thing is that when you subscribe an observer to an observable via observable.Subscribe(observer), all you get back is some anonymous IDisposable. Why?

As the talkers explain in that video, they could have given the IDisposable a more descriptive name (such as ISubscription), via a type name "alias" defined as follows:

interface ISubscription : IDisposable {}

However, they finally decided against this. They figured that once an ISubscription is returned from the Subscribe method, it would no longer be obvious that the returned value needs to be Diposed.

So that's another slightly problematic side of "interface inheritance" that one should keep in mind.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文