关于.net:为什么我们递归地实现接口?

Why do we implement interfaces recursively?

我理解任何集合(这里我讨论的是常规非泛型)都应该实现ICollection、IEnumerable和IList,以防常规对象集合或字典的IDictionary。

[尽管如此,我所问的问题并不特定于收藏]

IList是从ICollection和IEnumerable派生的

ICollection派生自IEnumerable

仅仅使集合(如arraylist)实现IList还不够吗?

在对象浏览器中,它显示集合类(例如ArrayList)正在实现IList、ICollection和IEnumerator。

我理解,即使我们指定了这三个集合,.NET也只接受一次定义。

但我的问题是,

  • 是否有任何最佳实践或建议指导我们为集合类(或与此类似的任何类)指定所有三个接口?

  • 或者仅仅是对象浏览器的属性将其显示为3个独立的实现?[刚检查发现它不是对象浏览器的属性。对象浏览器只显示在类定义中指定的接口]


  • 我相信只有对象浏览器才会这样显示。我刚试过这个:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    using System.Collections;
    using System.Collections.Generic;

    public class Foo : IEnumerable<int>, IEnumerable
    {
        public IEnumerator<int> GetEnumerator() { return null; }
        IEnumerator IEnumerable.GetEnumerator() { return null; }

    }

    public class Bar : IEnumerable<int>
    {
        public IEnumerator<int> GetEnumerator() { return null; }
        IEnumerator IEnumerable.GetEnumerator() { return null; }
    }

    将它加载到对象浏览器中会在两个类上显示两个接口。

    请注意,如果您从另一个实现继承接口,那么有时可能需要重新声明该接口——如果该接口以前是以显式或非虚拟方式实现的,那么它允许您重新实现该接口。我不认为是这样,但值得一提。

    不过,一般来说,您肯定不需要指定所有接口,我一般不会这样做。


    现在,我想你是在问

    1
    2
    3
    interface IA {};
    interface IB : IA {};
    interface IC : IB {};

    有什么区别:

    1
    class MyClass : IC {};

    1
    class MyClass : IA, IB, IC {};

    答案是,绝对没有。第二个版本使它的设计对其他程序员来说更加清晰,但两者都将生成相同的代码。


    Is it not just enough to make a collection (E.g. ArrayList) implement IList?

    这就够了。声明类:

    1
    2
    public MyCollectionClass : IList {
    }

    这意味着您的MyCollectionClass实现了IList、ICollection和IEnumerable。

    In the Object browser it is displaying that collection classes (E.g. ArrayList) are implementing IList, ICollection, and IEnumerator.

    这是对象浏览器的一个细节,或者基类只是通过指定所有接口实现了集合类。然而,确实没有任何驾驶理由这样做。


    我认为这对开发人员来说要么是明确的,要么有助于加强接口结构。我的意思是,假设您有一个用于数据结构类的接口,并且实现IDataObject。然后IDataObject实现了ISecurable和ILoggable。您创建的常规类可能只实现IDataObject,但如果IDataObject的创建者稍后更改实现并使其不可移植,会怎么样?这可能会更改代码的功能。因此,为了防止这种情况发生,当您创建从IDataObject继承的类时,您可以明确地说,为了安全起见,您还希望实现ISecurable和ILoggable。

    我不知道他们为什么和伊利斯特这样做,但这两个原因是我对为什么最好的猜测。


    为了通过接口访问对象,对象的类定义必须明确定义它实现接口…

    例如,我可以有以下内容:

    1
    2
    3
    interface IAnimal {
      public void Yelp();
    }

    以及以下类别:

    1
    2
    3
    4
    5
    class Dog {
      public void Yelp() {
         // do yelping
      }
    }

    现在,狗确实会叫;但是,因为它没有声明它实现了iAnimal,所以我不能执行以下操作:

    1
    2
    IAnimal poodle = new Dog();
    poodle.Yelp();

    要解决此问题,必须将dog的定义更改为:

    1
    2
    3
    4
    5
    class Dog : IAnimal {
      public void Yelp() {
         // do yelping
      }
    }