10

因此,很多时候我们都有一个接受 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 参数?

4

5 回答 5

12

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

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

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

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

像这样称呼:

Foo(Enumerable.AsList(o1, o2, o3));
于 2009-09-26T15:02:53.813 回答
3

有时我会使用带有“params”参数的方法。

Foo(params T[] ts)

如果我对 IEnumerable 死心塌地,我只需将该方法委托给需要 IEnumerable 的方法。

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

您必须调用 AsEnumerable 否则您将递归。

于 2009-09-26T15:03:28.663 回答
2

假设 Foo 需要一个 IEnumerable<T>,您可以利用类型推断并执行以下操作:

T o1, o2, o3;
Foo(new []{o1, o2, o3});
于 2009-09-26T15:01:56.227 回答
2

创建一个数组并传递它可能是在当前版本的 C# 中完成此任务的最简单/最优雅的方法。您可以利用隐式数组类型(即new[] { ... },但仅此而已。

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

let foo = seq [ o1; o2; o3 ]

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

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

于 2009-09-26T15:03:57.843 回答
0

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

Foo(o1, o2, o3);

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

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

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

void Foo(params IList<T> ts) { ... }
于 2009-09-26T15:18:48.133 回答