Каков самый простой и компактный способ создания IEnumerable или ICollection?

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

T o1, o2, o3;
Foo(new T[] { o1, o2, o3 });

Я всегда создавал массив или список, как в последнем примере. Но интересно, есть ли более элегантный способ создать необходимый IEnumerable или ICollection?

было бы совсем круто, если бы можно было сделать это:

Foo({ o1, o2, o3 });

и компилятор создаст наиболее абстрактную возможную коллекцию, которая удовлетворит потребности IEnumerable или ICollection (в зависимости от того, какую функцию принимает).

во всяком случае, как вы передадите O1, o2 и o3 к IEnumerable или параметрам ICollection?

5 ответов


текущая версия C# (3) поддерживает нотацию без явного типа, т. е.

Foo(new [] { o1, o2, o3 })

создать массив. Там же LINQ в это Enumerable.Range для создания непрерывного диапазона чисел. Все остальное должно быть реализовано. В духе Java:

public static IEnumerable<T> AsList<T>(params T[] values) {
    return values;
}

называться так:

Foo(Enumerable.AsList(o1, o2, o3));

иногда я использовал метод с аргументом "params".

Foo(params T[] ts)

и если я настроен на IEnumerable, у меня просто есть этот делегат метода тому, кто хочет IEnumerable.

Foo(params T[] ts) { Foo(ts.AsEnumerable()); }

вы должны вызвать AsEnumerable или вы собираетесь рекурсировать.


предполагая, что Foo ожидает IEnumerable, вы можете воспользоваться выводом типа и сделать:

T o1, o2, o3;
Foo(new []{o1, o2, o3});

Создание массива и передача, вероятно, самый простой / самый элегантный способ выполнить это в текущей версии C#. Вы можете воспользоваться преимуществами неявного ввода массива (т. е. new[] { ... }, но это все, что он идет.

Я подозреваю, что вы действительно ищете эквивалент C# этого синтаксиса F#:

let foo = seq [ o1; o2; o3 ]

, который генерирует IEnumerable<T> это будет повторяться над указанными элементами. ("Seq" на самом деле является псевдонимом F# для "IEnumerable", хотя F# имеет встроенный их поддержка.)

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


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

Foo(o1, o2, o3);

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

я советую не делать этого, если есть перегрузка Foo() это не принимает массив в этой позиции, потому что он может быстро сбивает с толку.

Я хочу, чтобы язык C# разрешил params на IList<T>:

void Foo(params IList<T> ts) { ... }