我最近开始探索lambda表达式,我想到了一个问题。假设我有一个需要不确定数量参数的函数。我会使用params关键字来建模可变数量的参数。
我的问题:我可以使用Lambda表达式做类似的事情吗?例如:
Func<int[], int> foo = (params numbers[]) =>
{
int result;
foreach(int number in numbers)
{
result += numbers;
}
return result;
}
如果是这样,两个子问题就出现了 - 是否有一种“好”的方式来编写这样的表达式,我甚至想在某个时候写出这样的表达式?
答案 0 :(得分:14)
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<>
代表更为直接。
答案 1 :(得分:2)
我认为你能得到的最接近的东西是这样的:
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, ...}
答案 2 :(得分:1)
这里有两件事,LHS上的Func<int[], int>
泛型委托和RHS上的lambda表达式。前者是不可能的,因为Func<S, T>
委托被声明为:
public delegate TResult Func<in T, out TResult>(T arg); //ie no params involved
您需要自己的代理接受params
输入,如接受的答案所示。
后者,问题标题是什么,在C#中也不可能,但是有一个原因。
赋值表达式的LHS是一个编译时间的东西(除非它当然是dynamic
但是编译器再次意识到它)并且它的RHS是运行时的东西(当然除非{{1} }} S)。编译器可以推断LHS上键入的内容,但它仅在运行时获取RHS上的值,即代码运行时。当你输入这个:
const
Func<int[], int> foo = ....
始终被视为foo
。如果必须解密RHS,它将给编译器增加很多复杂性。对于例如如果您尝试的是可能的,请考虑这种情况:
Func<int[], int>
相反,当您编写自己的委托接受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?
时,您直接告诉编译器(即从LHS知道)。
命名方法的参数支持的三个特性,即params
,out/ref
,可选参数,lambda表达式(甚至早期的params
语法)仅支持{{ 1}}。