创建IEnumerable <t>或ICollection <t>的最简单,最紧凑的方法是什么?</t> </t>

时间:2009-09-26 14:58:35

标签: c# .net ienumerable icollection function-parameter

因此,很多时候我们有一个接受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 个答案:

答案 0 :(得分:11)

当前版本的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));

答案 1 :(得分:3)

有时我使用了一个带有“params”参数的方法。

Foo(params T[] ts)

如果我已经死在IEnumerable上,我只需要将该方法委托给想要IEnumerable的那个。

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

你必须打电话给AsEnumerable,否则你将要进行递归。

答案 2 :(得分:2)

假设Foo期望IEnumerable&lt; T&gt;,您可以利用类型推断并执行:

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

答案 3 :(得分:2)

在当前版本的C#中创建一个数组并传递它可能是最简单/最优雅的方法。你可以利用隐式数组类型(即new[] { ... },但这是最直接的。

我怀疑你真的在寻找这种F#语法的C#等价物:

let foo = seq [ o1; o2; o3 ]

生成IEnumerable<T>,它将迭代指定的元素。 ('Seq'实际上是'IEnumerable`的F#别名,尽管F#内置了对它们的支持。)

不幸的是,由于这是一个功能很强的概念,因此没有C#等价物 - 尽管谁知道它何时会被添加,因为C#变得越来越实用。

答案 4 :(得分:0)

如果您有一个将数组作为最后一个参数的方法,那么标记该参数params可能是有意义的。这使您可以像这样调用方法:

Foo(o1, o2, o3);

我在为Foo()编写单元测试时发现这特别有用,因为通常在单元测试中,我的参数是这样的,而不是在数组中。

如果Foo()的重载没有在该位置使用数组,我建议不要这样做,因为它可能会很快混淆。

我确实希望C#语言允许params使用IList<T>

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