C#为`WhereWithIndex`写一个类型签名

时间:2016-01-01 18:07:34

标签: c# generics collections functional-programming extension-methods

在看到指定如何使用Linq使用集合枚举索引的答案后,我决定编写一个与WhereWithIndex类似的扩展方法Where,但输入函数应该有两个参数,项目和索引。

示例用法应为:

names = new String[] {"Bob", "Alice", "Luke", "Carol"}
names.WhereWithIndex( (_, index) => index % 2 == 0 ) // -> {"Bob", "Luke"}

我已经能够将这个逻辑内联到我的程序中,它看起来像这样:

iterable
  .Select((item, index) => new {item, index})
  .Where(x => condition(item, index))
  .Select(x => x.item);

但我应该给这个扩展方法的类型签名仍然没有找到我。我试过了:

public static IEnumerable<T> WhereWithIndex(this IEnumerable<T> iterable, Predicate<T, int> condition) {

因为我想要输入一些我无法用intString标记的内容,所以我尝试使用T来表示一般性following the official documentation,条件是一个谓词,所以我这样说。如何表达具有2个参数的委托的类型进一步包括我,我尝试使用逗号分隔参数,但我只是猜测为I could only fund examples of predicates with only one input

它给了我错误:

Example.cs(22,29): error CS0246: The type or namespace name `T' could     
not be found. Are you missing an assembly reference?

有关写这种签名的想法吗?如果它在C#版本6中更简单,那么也可以提及它。

1 个答案:

答案 0 :(得分:3)

Wherepublic static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate); 可以做到这一点。它有这个签名:

<TSource>

您的签名遗失的唯一内容是Where旁边的Func<TSource, int, bool>。这告诉编译器函数是通用的。另外使用Predicate<T, int>代替Func<P1, P2, P3, R>。在C#中,public R MyFunction(P1 p1, P2 p2, P3 p3) { ... } 是一个接收P1,P2,P3并返回R的函数,例如:

Action<P1, P2>

另一方面,public void MyAction(P1 p1, P2 p2) { ... } 是一个取P1和P2并且不返回任何内容的函数:

MyFunction

请注意,在这些示例中,MyActionpublic void MyAction<P1, P2>(P1 p1, P2 p2) { ... } 不是泛型(P1..P3和R需要是实际类型)。如果您想将其设为通用,则将其更改为:

"/*" (~["*"])* "*" (~["*","/"] (~["*"])* "*" | "*")* "/"

在这种情况下,P1和P2是任意类型的变量名。