Linq .Select() / .SelectMany() 自动使用第二个可选参数
Linq .Select() / .SelectMany() automatically uses second, optional parameter
我刚发现 Linq 中最奇怪的行为:
在调用一元函数时,我喜欢只传递函数名,而不是
var foo = myList.Select(item => MyFunc(item));
我写
var foo = myList.Select(MyFunc);
应该是一样的。只有在某些情况下,它不是!也就是说,如果函数有第二个参数,它是一个 int
和可选的:
private string MyFunc(string input, int foo = 0)
{
...
}
在这种情况下,语句
var foo = myList.Select(MyFunc);
等于
var foo = myList.Select((item, index) => MyFunc(item, index));
如果第二个参数不是可选的或不是 int
,编译器会报错,但在这种情况下,它只是偷偷地给你一个惊喜。
有其他人遇到过这个吗?还有哪些其他 Linq 表达式以这种方式工作? (到目前为止,.SelectMany()
确实如此)。解决此行为的最优雅方法是什么(并防止其他人陷入同样的陷阱?)
这实际上不是特定 LINQ 扩展方法的问题,而是如何处理 Func
s 和 Action
s 的可选参数,简而言之 - 它们不是,它们被认为是常规的选择相应的 Func
/Action
签名时省略参数和默认值。看这里 Optional Parameters, No overload for 'Employee' matches delegate 'System.Func<Employee> or here .
换句话说,你的 MyFunc
不能用作 Func<string, string>
,你必须使用 Func<string, int, string>
,在 Select
的情况下恰好作为重载存在添加了索引。
我刚发现 Linq 中最奇怪的行为:
在调用一元函数时,我喜欢只传递函数名,而不是
var foo = myList.Select(item => MyFunc(item));
我写
var foo = myList.Select(MyFunc);
应该是一样的。只有在某些情况下,它不是!也就是说,如果函数有第二个参数,它是一个 int
和可选的:
private string MyFunc(string input, int foo = 0)
{
...
}
在这种情况下,语句
var foo = myList.Select(MyFunc);
等于
var foo = myList.Select((item, index) => MyFunc(item, index));
如果第二个参数不是可选的或不是 int
,编译器会报错,但在这种情况下,它只是偷偷地给你一个惊喜。
有其他人遇到过这个吗?还有哪些其他 Linq 表达式以这种方式工作? (到目前为止,.SelectMany()
确实如此)。解决此行为的最优雅方法是什么(并防止其他人陷入同样的陷阱?)
这实际上不是特定 LINQ 扩展方法的问题,而是如何处理 Func
s 和 Action
s 的可选参数,简而言之 - 它们不是,它们被认为是常规的选择相应的 Func
/Action
签名时省略参数和默认值。看这里 Optional Parameters, No overload for 'Employee' matches delegate 'System.Func<Employee> or here
换句话说,你的 MyFunc
不能用作 Func<string, string>
,你必须使用 Func<string, int, string>
,在 Select
的情况下恰好作为重载存在添加了索引。