Почему мы реализуем интерфейсы рекурсивно? - PullRequest
6 голосов
/ 16 августа 2010

Я понимаю, что любая Коллекция (здесь я говорю о обычном неуниверсальном) должна была реализовывать ICollection, IEnumerable и IList в случае обычной коллекции объектов или IDictionary в случае словарей.

[Тем не менее вопросЯ спрашиваю не относится только к коллекциям]

IList получен из ICollection, а IEnumerable

ICollection получен из IEnumerable

Разве этого недостаточно для создания коллекции (например, ArrayList) реализовать IList?

В браузере объектов отображается, что классы коллекций (например, ArrayList) реализуют IList, ICollection и IEnumerator.

Я понимаю, что даже если мы укажем все три коллекции,.Net собирается принять определения только один раз.

Но мой вопрос таков:

  1. Есть ли рекомендации или рекомендации, которые помогут нам указать все три интерфейса для класса коллекции (или любого класса, подобного этому)?

  2. Или это просто свойство Object Browser, которое отображает его как 3 отдельные реализации?[Только что проверил и обнаружил, что это не собственность браузера объекта.Обозреватель объектов просто отображает интерфейсы, указанные в определении класса]

Ответы [ 5 ]

5 голосов
/ 16 августа 2010

Я считаю это просто объектный браузер, который отображает это таким образом. Я только что попробовал это:

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

Загрузка этого в браузер объектов показала оба интерфейса на обоих классах.

Обратите внимание, что иногда может быть точкой повторного выделения интерфейса, если вы наследуете от другой реализации - это позволяет вам переопределить интерфейс, если он ранее был реализован явно не виртуальным способом. Я не верю, что это так, но стоит упомянуть.

В общем, вам определенно не обязательно указывать все интерфейсы, и я бы не стал этого делать.

2 голосов
/ 16 августа 2010

Теперь, я думаю, вы спрашиваете, учитывая

interface IA {};
interface IB : IA {};
interface IC : IB {};

В чем разница между:

class MyClass : IC {};

и

class MyClass : IA, IB, IC {};

И ответ таков: абсолютно ничего . Вторая версия делает его дизайн немного понятнее для других программистов, но любой из них будет генерировать идентичный код.

2 голосов
/ 16 августа 2010

Разве недостаточно просто сделать коллекцию (например, ArrayList) для реализации IList?

Достаточно. Объявление класса:

public MyCollectionClass : IList {
}

Это будет означать, что ваш MyCollectionClass реализует IList, ICollection и IEnumerable.

В обозревателе объектов отображается, что классы коллекции (например, ArrayList) реализуют IList, ICollection и IEnumerator.

Это либо деталь Object Browser, либо базовый класс просто реализовал классы коллекции, указав все интерфейсы. Однако на самом деле нет никаких оснований для этого.

1 голос
/ 17 августа 2010

Я полагаю, что это либо должно быть понятно разработчикам, либо помочь реализовать структуру интерфейса.Я имею в виду, что у вас есть интерфейс для классов структуры данных, и вы реализуете IDataObject.Затем IDataObject реализует ISecurable и ILoggable.Обычные классы, которые вы создаете, могут просто реализовать IDataObject, но что, если создатель IDataObject изменит реализацию позже и отбросит ILoggable?Это может изменить функциональность вашего кода.Итак, чтобы предотвратить это, когда вы создаете свой класс, который наследует от IDataObject, вы можете явно сказать, что вы хотите также реализовать ISecurable и ILoggable, просто чтобы быть в безопасности.

Я не знаю точно, почему онисделал это с IList, но эти две причины - мое лучшее предположение о том, почему.

1 голос
/ 16 августа 2010

Чтобы получить доступ к объекту через интерфейс, определение класса для объекта должно явно определять, что он реализует интерфейс ...

Например, я могу иметь следующее:

interface IAnimal {
  public void Yelp();
}

и следующий класс:

class Dog {
  public void Yelp() { 
     // do yelping
  }
}

Теперь собака действительно вскрикивает;однако, поскольку он не объявляет, что он реализует IAnimal, я не могу сделать следующее:

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

Чтобы исправить это, определение для Dog должно быть изменено на:

class Dog : IAnimal {
  public void Yelp() { 
     // do yelping
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...