Пользовательская коллекция с использованием IEnumerable и ICollection против IList

Мне нужно создать свой собственный заказ GenericCollection учебный класс. Теперь у меня есть много вариантов, чтобы получить его с помощью IEnumerable, ICollection, а также IListгде позже предлагает некоторые дополнительные функции.

Я немного запутался, что если я пойду с IEnumerable<T> мне может потребоваться объявить объект на самом деле держать коллекцию, как в этом случае _list,

public class GenericCollection<T> : IEnumerable<T>
{
    private List<T> _list;
    //...
}

Но если я пойду с ICollection<T> или же IList<T>Я не требую декларировать List объект как он неявно доступен.

public class GenericCollection<T> : IList<T>
{
    // no need for List object
    //private List<T> _list; 
    //...
}

В чем разница между этими двумя подходами в отношении производительности?

В каком сценарии каждый из них предпочтительнее, особенно когда речь идет о разработке собственной коллекции. Я заинтересован в легкой коллекции с хорошей производительностью. Я думаю, что это может быть достигнуто с помощью IEnumerable<T> но как именно вместе с некоторыми вескими причинами пойти с этим?

Я просмотрел некоторые существующие посты, но ни одна не дает необходимой информации.

Возвращение "IList" против "ICollection" против "Collection"

3 ответа

Решение

IEnumerable, ICollection, а также IList (как правило, любой тип с I префикс) просто интерфейсы. Они позволяют вам показать, что будет делать ваш класс, но в отличие от того, что вы наследуете класс, интерфейсы не предоставляют вам реализацию по умолчанию ни одной из вещей, которые, по их словам, вы должны делать.

Что касается выбора интерфейса, вот краткое руководство:

  • IList является ICollection к которому можно получить доступ по индексу.
  • ICollection является IEnumerable с легким доступом к таким вещам, как Add, Remove, а также Count,
  • IEnumerable это все, что можно перечислить, даже если список этих вещей не существует, пока вы не перечислите его.

Некоторые классы, которые вы, возможно, захотите расширить (или оставить в качестве частного поля, которое выполняет большую часть логики) для вашей коллекции: List<T>, Collection<T>, (который реализует IList<T>, но с более легким доступом к переопределенной реализации, см. Коллекция и Список, что вы должны использовать в своих интерфейсах? за большие различия между этими двумя) ObservableCollection<T>или коллекции, которые не являются списками, как Dictionary<T, U> а также HashSet<T>, Для получения дополнительной информации по любому из них посмотрите документацию MSDN по классу.

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

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

Производительность вряд ли будет зависеть от того, какие интерфейсы реализованы. Это скорее зависит от того, сколько инструкций процессор должен выполнить для достижения определенной цели. Если вы реализуете IEnumerable и переносите его по списку, вы, скорее всего, в конечном итоге будете писать методы Add/Remove/this[], которые просто распространяют вызовы в список, что увеличило бы производительность. Следовательно, хотя я не проводил никаких измерений, подход наследования, вероятно, был бы немного быстрее.

Однако такие детали обычно имеют значение только для приложений реального времени, которым крайне необходимо сохранять каждый возможный цикл ЦП. У Эрика Липперта есть отличная статья о том, как обратить внимание на такие детали: http://blogs.msdn.com/b/ericlippert/archive/2003/10/17/53237.aspx. Как правило, вам лучше использовать подход, который лучше соответствует бизнес-логике и архитектуре вашего приложения, а не деталям производительности.

Другие вопросы по тегам