Параметры IEnumerable <T>c # - PullRequest
       19

Параметры IEnumerable <T>c #

56 голосов
/ 24 января 2010

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

Ответы [ 3 ]

92 голосов
/ 25 января 2010

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

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

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

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

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


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

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


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

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

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

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

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.

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

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

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

12 голосов
/ 24 января 2010

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

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);
4 голосов
/ 24 января 2010

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

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

TheMethod(theIEnumerable.ToArray());
...