Почему делает IEnumerable <T>, наследовались IEnumerable?

В Java все находится в форме класса.

Если вы хотите использовать любой объект, тогда у вас есть две фазы:

  1. Объявить
  2. Инициализация

Пример:

  • Объявление: Object a;
  • Инициализация: a=new Object();

То же самое для концепции массива

  • Объявление: Item i[]=new Item[5];
  • Инициализация: i[0]=new Item();

Если вы не дают секцию инициализации, тогда возникает NullpointerException.

36
задан Timwi 23 August 2010 в 19:37
поделиться

4 ответа

Прямой из первых уст (Hejlsberg):

Идеально все интерфейсы универсального набора (например, ICollection<T>, IList<T>) наследовались бы их неуниверсальным дубликатам, таким образом, что универсальные интерфейсные экземпляры могли использоваться и с универсальным и неуниверсальным кодом. Например, было бы удобно, если IList<T> мог бы быть передан для кодирования, который ожидает IList.

Как оказалось, единственный универсальный интерфейс, для которого это возможно, IEnumerable<T>, потому что [только 115] - контравариант: В IEnumerable<T>, параметр типа T используется только в "выходных" положениях (возвращаемые значения) а не во "входных" положениях (параметры). ICollection<T> и IList<T> использование T и во входных и выходных положениях и в тех интерфейсах являются поэтому инвариантными. (Как в стороне, они были бы контравариантом, если T использовался только во входных положениях, но это действительно не имеет значения здесь.)

<... надрез...>

Так, для ответа на вопрос, IEnumerable<T> наследовался от [1 110], потому что это может!:-)

50
ответ дан Timwi 27 November 2019 в 05:45
поделиться

Ответ для IEnumerable: "потому что это может, не влияя на безопасность типов".

IEnumerable интерфейс "только для чтения" - таким образом, не имеет значения, что универсальная форма более конкретна, чем неуниверсальная форма. Вы ничего не повреждаете путем реализации обоих. IEnumerator.Current возвраты object, тогда как IEnumerator<T>.Current возвраты T - это хорошо, поскольку можно всегда законно преобразовывать в object, хотя это может означать упаковывать.

Сравнивают это с IList<T> и IList - можно звонить Add(object) на IList, тогда как это может быть недопустимо для какого-то конкретного IList<T> (что-либо кроме [1 112] на самом деле).

Brad Abram занесенный в блог с ответом Anders об этом самом вопросе.

17
ответ дан Jon Skeet 27 November 2019 в 05:45
поделиться

Это для обратной совместимости. Если Вы вызываете функцию.Net 1.1, которая ожидает ваниль IEnumerable, можно передать в универсальном IEnumerable.

Luckilly универсальный IEnumerator наследовался IEnumerator

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

    private IEnumerator<string> Enumerator() {
        // ...
    }

    public IEnumerator<string> GetEnumerator() {
        return Enumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
        return Enumerator();
    }
3
ответ дан Mendelt 27 November 2019 в 05:45
поделиться

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

2
ответ дан Jon Skeet 27 November 2019 в 05:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: