C# lambda表达式作为函数参数

19
我最近一直在研究lambda表达式,有些特定的功能我一直想学习,但就是无法理解。假设我的代码中有以下逻辑:
List<A> foo; // assuming this is populated
string[] bar = foo.Select<A,string>(x => x.StringProperty).ToArray<string>();

现在,我希望将整个操作抽象成一个处理程序方法,这样我就可以做到这一点:
string[] bar = MakeArray<A,string>(foo, x => x.StringProperty);
int[] foobar = MakeArray<A,int>(foo, x => x.IntegerProperty);

我该如何编写这个方法的主体呢?我预见将签名声明为以下内容:

U[] MakeArray<T,U>( /* some lambda magic? */ ) where T : IEntity {}

但我不知道如何指定我期望一个lambda表达式作为方法参数,并且这将如何转换为方法的主体。

有人能向我展示如何创建上面的MakeArray()函数吗?我相信一旦我看到它是如何完成的,我就能从那里继续。

编辑

正如评论中指出的那样,MakeArray()需要对IEnumerable<>进行引用。已更新以反映此更改。


5
对于代码的泛型隐式特性,在每个语句中不需要显式地声明类型,这可能会增加代码的可读性,但这种效果可能因人而异。以下语句与您的第一个选择语句相同.. string[] bar = foo.Select(x => x.StringProperty).ToArray(); - Quintin Robinson
如果你发现自己在代码中到处使用数组,你可能需要考虑将它们重构为 IEnumerable<T>IList<T>。这样就不需要这些了。另外,MakeArray 需要引用 foo 吗? - BlueRaja - Danny Pflughoeft
@ Quintin ~ 是的,我有点喜欢显式声明泛型(在适用时) ,这样就清楚我要提取什么了。不过你说得对。 - Richard Neil Ilagan
@BlueRaja ~ 嗯,数组只是为了举例说明。但是,我明白你的观点! - Richard Neil Ilagan
5个回答

16
public static U[] MakeArray<T, U>(this IEnumerable<T> @enum, Func<T, U> rule)
{
    return @enum.Select(rule).ToArray();
}

+1 谢谢!我选择这个答案来展示方法中传入的 Func<> 参数是如何使用的。真的很有帮助。 - Richard Neil Ilagan

13

请尝试以下操作:

U[] MakeArray<T,U>(Func<T, U> projection) where T : IEntity {
  ...
}

在将Lambda表达式作为参数传递时,通常希望匹配的参数是一个委托。在大多数情况下,您应该只使用适当的Action<>Func<>值。前者用于返回void的lambda表达式,后者用于返回值的lambda表达式。


2

您正在寻找Action<>Func<>


2

谢谢您提供链接!我一直想知道他们是如何实现所有这些魔法的。 - Colin

1

您可以创建扩展

public static class MakeArrayExtension
{
    public static U[] MakeArray<T, U>(this IEnumerable<T> collection, Func<T,U> func)
    {
        return collection.Select(func).ToArray();
    }
}

然后像这样使用它

List<A> foo; // assuming this is populated
string[] bar = foo.MakeArray<A,string>(x => x.StringProperty);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接