14

我最近开始探索 lambda 表达式,我想到了一个问题。假设我有一个需要不确定数量的参数的函数。我会使用 params 关键字来对可变数量的参数进行建模。

我的问题:我可以用 Lambda 表达式做类似的事情吗?例如:

Func<int[], int> foo = (params numbers[]) =>
                       {
                           int result;

                           foreach(int number in numbers)
                           {
                               result += numbers;
                           }

                           return result;
                       }

如果是这样,就会出现两个子问题 - 是否有一种“好”的方式来编写这样的表达式,我什至想在某个时候写这样的表达式?

4

3 回答 3

18

嗯,有点。首先,Func<>您需要定义一个自定义委托,而不是使用 :

public delegate int ParamsFunc (params int[] numbers);

然后,您可以编写以下 lambda:

ParamsFunc sum = p => p.Sum();

并使用可变数量的参数调用它:

Console.WriteLine(sum(1, 2, 3));
Console.WriteLine(sum(1, 2, 3, 4));
Console.WriteLine(sum(1, 2, 3, 4, 5));

但老实说,坚持使用内置Func<>委托确实要简单得多。

于 2012-06-26T20:13:23.883 回答
3

我认为你能得到的最接近的东西是这样的:

Func<int[], int> foo = numbers[] =>
                       {
                           // logic...
                       }

var result = foo(Params.Get(1, 5, 4, 4, 36, 321, 21, 2, 0, -4));

并且有:

public static class Params
{
    public static T[] Get(params T[] arr)
    {
        return arr;
    }
}

但我看不出这比简单new[] {1, 5, 4, 4, ...}

于 2012-06-26T20:08:15.857 回答
1

这里有两件事,Func<int[], int>LHS 上的通用委托和 RHS 上的 lambda 表达式。前者是不可能的,因为Func<S, T>委托声明如下:

public delegate TResult Func<in T, out TResult>(T arg); //ie no params involved

您需要自己的代表来接受params输入,如接受的答案所示。

后者,也就是问题标题的含义,在 C# 中也是不可能的,但这是有原因的。

赋值表达式的 LHS 是编译时的东西(除非它dynamic当然是但编译器再次意识到它),它的 RHS 是运行时的东西(当然除非在consts 的情况下)。编译器可以推断在 LHS 上键入了什么,但它仅在运行时(即代码运行时)获取 RHS 上的值。当您键入以下内容时:

Func<int[], int> foo = ....

foo总是被认为是Func<int[], int>。如果必须破译 RHS,它将给编译器增加很多复杂性。例如,如果您尝试的是可能的,请考虑以下情况:

Func<int[], int> foo = (params int[] numbers) =>
                   {
                       int result;

                       foreach(int number in numbers)
                       {
                           result += numbers;
                       }

                       return result;
                   };

//and later at some other place
foo = (int[] numbers) => 0;

//how would you call 'foo' now?

相反,当您编写自己的接受委托时params,您是在直接告诉编译器(即从 LHS 获知)

在命名方法的参数支持的三个特性中,即,out/ref可选params参数,lambda 表达式(甚至更早的delegate语法)仅支持out/ref

于 2013-12-22T03:45:49.053 回答