Параметр IEnumerable <T> С#

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

Ответ 1

Почему я не могу использовать IEnumerable с параметрами?

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

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

Функция "params enumerable" была рассмотрена и спроектирована. Он никогда не был указан, реализован, протестирован, документирован или отправлен.

Следовательно, вы не можете использовать эту функцию.


ОБНОВЛЕНИЕ: На момент написания этой статьи - начало 2015 года - теперь указано, но реализация, тестирование, документация и доставка были сокращены для С# 6.0 во второй половине 2014 года. См. объявление Lucian здесь: http://roslyn.codeplex.com/discussions/568820.

Поскольку он до сих пор не был реализован, протестирован, задокументирован и отправлен, такой функции пока нет. Надеюсь, это превратит его в гипотетическую будущую версию С#.


ОБНОВЛЕНИЕ: я должен уточнить, что я имею в виду под "функцией", поскольку, возможно, у всех нас есть разные идеи, что такое "особенность". Функция, о которой я говорю, это позволить вам сказать что-то вроде

void Frob(params IEnumerable<int> x)
{
    foreach(int y in x) ...
}

а затем сайт вызова может либо находиться в "нормальной форме" передачи последовательности целых чисел, либо "расширенной формы" Frob (10, 20, 30). Если в расширенной форме компилятор генерирует вызов, как если бы вы сказали Frob (новый int [] {10, 20, 30}), то же, что и для param-массивов. Суть функции заключается в том, что часто бывает, что метод никогда не использует случайный доступ к массиву, и поэтому мы могли бы ослабить требование о том, чтобы params были массивом. Параметры могут быть просто последовательностью.

Вы можете сделать это сегодня, сделав перегруз:

void Frob(params int[] x) { Frob((IEnumerable<int>)x); }

void Frob(IEnumerable<int> x)
{
    foreach(int y in x) ...
}

что немного больно. Мы могли бы просто позволить вам использовать IEnumerable в качестве типа аргумента params и делать с ним.

Будет ли это исправлено?

Надеюсь. Эта функция была в списке в течение длительного времени. Это привело бы к тому, что многие функции будут работать гораздо лучше с LINQ.

Frob(from c in customers select c.Age);

без необходимости писать две разные версии Frob.

Однако это просто "небольшое удобство"; на самом деле это не добавляет много нового к языку. Поэтому он никогда не делал его достаточно высоким в списке приоритетов, чтобы перейти к этапу "спецификация написана".

Мне очень жаль, что они не переписали старые библиотеки на использование дженериков.

Комментарий отмечен.

Ответ 2

А, я думаю, теперь я понял, что вы имеете в виду. Я думаю, вы хотите, чтобы объявить метод следующим образом:

public void Foo<T>(params IEnumerable<T> items)
{
}

И тогда сможете вызвать его с помощью "нормального" аргумента следующим образом:

IEnumerable<string> existingEnumerable = ...;
Foo(existingEnumerable);

или с несколькими параметрами, например:

Foo("first", "second", "third");

Это то, что тебе нужно? (Отмечая, что вы хотите, чтобы первая форма использовала T=string, а не T=IEnumerable<string> с одним элементом...)

Если это так, я согласен, что это может быть полезно - но достаточно легко:

public void Foo<T>(params T[] items)
{
    Foo((IEnumerable<T>) items);
}

public void Foo<T>(IEnumerable<T> items)
{
}

Я не нахожу, что делаю это достаточно часто, чтобы сделать вышеупомянутое особенно уродливым обходным путем.

Обратите внимание, что при вызове вышеуказанного кода вам нужно явно указать аргумент типа, чтобы избежать компилятора, предпочитающего пример params. Так, например:

List<string> x = new List<string>();
Foo<string>(x);

Ответ 3

Параметры params отправляются как массив, а IEnumerable<T> не предоставляет произвольный доступ, который требуется для работы в качестве массива.

Вам нужно создать массив из IEnumerable, когда вы вызываете метод:

TheMethod(theIEnumerable.ToArray());