关于c#:创建IEnumerable< T>的最简单,最紧凑的方法是什么?

What is the easiest and most compact way to create a IEnumerable<T> or ICollection<T>?

所以,很多时候我们有一个函数接受IEnumerable或ICollection作为参数。如果我们有单个项,但没有集合来保存它们,则必须在将它们传递给函数之前创建集合,例如:

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

我总是创建一个数组或列表,就像我在上一个示例中所做的那样。但是我想知道,有没有一种更优雅的方式来创建所需的IEnumerable或ICollection?

如果你能做到这一点,那就太酷了:

1
Foo({ o1, o2, o3 });

编译器将创建尽可能抽象的集合,以满足IEnumerable或ICollection的需要(取决于函数接受哪个集合)。

总之,如何将o1、o2和o3传递给IEnumerable或ICollection参数?


当前版本的C(3)支持不带显式类型的表示法,即

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

创建数组。还有Linq的Enumerable.Range来创建一个连续的数字范围。其他的一切都必须实施。以Java精神:

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

这样称呼:

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


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

1
Foo(params T[] ts)

如果我已经对IEnumerable有了固定的设置,我只需要将该方法委托给想要IEnumerable的方法。

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

你必须打一个可数的电话,否则你会再次出现。


创建一个数组并传递,这可能是在当前版本的C_中实现这一点的最简单/最优雅的方法。您可以利用隐式数组类型(即new[] { ... }类型),但仅此而已。

我怀疑你真的在寻找这个f语法的c等价物:

1
let foo = seq [ o1; o2; o3 ]

它生成一个将在指定元素上迭代的IEnumerable。(‘seq’实际上是‘ienumerable’的f别名,尽管f内置了对它们的支持。)

不幸的是,由于这是一个基本的功能性概念,所以没有C等价物——尽管谁知道何时会添加它,因为C变得越来越功能性。


假设foo需要IEnumerable,则可以利用类型推断并执行以下操作:

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

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

1
Foo(o1, o2, o3);

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

我建议不要这样做,如果有一个Foo()的过载不采取一个数组在那个位置,因为它会很快变得混乱。

我希望C语言允许params用于IList

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