Добавить (T объект) не является методом контракта IEnumerable <T>- Почему? - PullRequest
1 голос
/ 18 декабря 2009

Мне показалось странным, что любой класс, который наследуется от IEnumerable<T>, не должен реализовывать Add(T object), даже если вы хотите использовать инициализаторы коллекции при инициализации экземпляра класса, у вас есть реализовать Add(T object).

Почему это так?

Ответы [ 5 ]

6 голосов
/ 18 декабря 2009

IEnumerable<T> - интерфейс только для чтения - он предназначен только для представления «последовательности».

Инициализаторам коллекции для работы требуется Add, но они проверяют, что тип сначала реализует IEnumerable, чтобы убедиться, что это действительно тип коллекции некоторого описания. Им не требуется универсальная форма, так как это было бы ограничительным для некоторого кода до версии 2.0 (в частности, различные коллекции пользовательского интерфейса не поддерживают IEnumerable<T> IIRC), и они не требуют специфических Add подпись в качестве инициализаторов коллекции может использоваться с разным количеством аргументов. Например, Dictionary<TKey, TValue> имеет Add(TKey value, TValue value), поэтому вы можете использовать:

var dictionary = new Dictionary<string, int>
{
    { "Jon", 33 },
    { "Tom", 6 }
};

Это означает, что он не может быть ограничен (скажем) IList, который имеет только метод с одним аргументом Add. В некоторой степени требуется утка, но требование IEnumerable является попыткой убедиться, что Add действительно означает «добавить элемент в коллекцию», а не что-то совершенно иное. Компилятор не использует тот факт, что он реализует IEnumerable - он никогда не вызывает GetEnumerator, например, при построении коллекции.

2 голосов
/ 18 декабря 2009

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

Ваш более широкий вопрос о том, почему инициализаторам коллекции требуется сочетание IEnumerable и метода Add, вероятно, лучше всего решит Мадс Торгерсен :

Что такое коллекция?

Что мы тогда нашли? Только 14 наших собственные (публичные) классы (с публичными конструкторы) реализовать ICollection<T>! Очевидно, есть намного больше коллекций в рамках, так что было ясно, что нам нужны некоторые Другой способ сказать, что-то это класс коллекции LINQ к спасти еще раз: с модифицированным версии запроса было легко установить, что среди нашей общественности классы с публичными конструкторами там являются:

  • 189 с публичной Add метод и реализовать System.Collections.IEnumerable

  • 42, которые имеют общедоступный Add метод, но не реализовать System.Collections.IEnumerable

Если вы посмотрите на классы, возвращаемые эти два запроса, вы понимаете, что Есть по существу два принципиально разные значения Название «Добавить»:

а) Вставьте аргумент в коллекция или

б) Вернуть арифметическую сумму аргумент и получатель.

Люди на самом деле очень хороши в (прямо или косвенно) реализация неуниверсальный IEnumerable интерфейс при написании коллекционных классов, так это оказывается довольно надежным индикатор того, является ли метод Add первый или второй вид. Таким образом, для наши цели оперативный ответ на заголовок вопроса становится:

Коллекция - это тип, который реализует IEnumerable и имеет общедоступный Add Метод

0 голосов
/ 18 декабря 2009

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

Например, вы можете использовать IEnumerable с командой Yield для вычисления простых чисел или последовательности Фибоначчи. Это действительно зависит от вас.

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

Мои два цента.

0 голосов
/ 18 декабря 2009

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

0 голосов
/ 18 декабря 2009

Поскольку IEnumerable<T> - это интерфейс для перечисления коллекции, ничего больше.

С MSDN :

Выставляет перечислитель, который поддерживает простая итерация по коллекции указанного типа.

...