Mor*_*eng 9 c# linq select expression
Enumerable.SelectMany有4个重载签名.为简单起见,我们忽略了带有int参数的两个签名.所以我们有4个SelectMany签名:
public static IEnumerable<TResult> SelectMany<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, IEnumerable<TResult>> selector
)
public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(
this IEnumerable<TSource> source,
Func<TSource, IEnumerable<TCollection>> collectionSelector,
Func<TSource, TCollection, TResult> resultSelector
)
Run Code Online (Sandbox Code Playgroud)
我的问题是:在将LINQ表达式转换为扩展方法调用时,C#编译器如何选择SelectMany?
基本上,如果LINQ表达式中有多个from,则会有SelectMany.但是,似乎C#编译器只选择第二个签名.永远不会使用第一个签名.
IEnumerable<int> en1 = Enumerable.Range(1, 3);
IEnumerable<double> en2 = new double[] { 1.0, 3.14 };
IEnumerable<string> en3 =
from i1 in en1
from i2 in en2
select (i1 * i2).ToString();
foreach (var i in en3)
{
Console.WriteLine(i);
}
Run Code Online (Sandbox Code Playgroud)
在Reflector的帮助下,我可以看到上面的LINQ表达式被翻译成了
en1.SelectMany<int, double, string>(delegate (int i1) {
return en2;
}, delegate (int i1, double i2) {
double CS$0$0000 = i1 * i2return CS$0$0000.ToString();
})
Run Code Online (Sandbox Code Playgroud)
以上示例涉及3种类型.因此,选择第二个SelectMany签名是合理的.但是,对于下面的示例,仅涉及一种类型,它仍然选择第二个签名.
IEnumerable<int> en4 =
from i1 in en1
from i2 in Enumerable.Range(0, i1)
select i2;
Run Code Online (Sandbox Code Playgroud)
它被翻译成:
en1.SelectMany<int, int, int>(delegate (int i1) {
return Enumerable.Range(0, i1);
}, delegate (int i1, int i2) {
return i2;
})
Run Code Online (Sandbox Code Playgroud)
所以,我找不到将LINQ表达式转换为第一个SelectMany签名的情况.有这种情况吗?
如果没有使用第一个SelectMany签名,那么它的存在只是因为它在函数式编程中是monad的BIND?
也许问题可能是:为什么我们有2个SelectMany签名?
谢谢.
根据C#Spec,编译器不会生成对第一版SelectMany的重载调用.SelectMany的第一个版本可用于将列表列表展平为单个平面列表.
public IEnumerable<string> Example(IEnumerable<IEnumerable<string>> enumerable) {
return enumerable.SelectMany(x => x);
}
Run Code Online (Sandbox Code Playgroud)
它在查询表达式中没有强大的等价物.
有关详细信息,请参阅C#语言规范的第7.15.2节.
为什么我们有2个SelectMany签名?
所以我可以在我的代码中使用第一个.
var orders = Customers.SelectMany(c => c.Orders)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3795 次 |
| 最近记录: |