当前位置:  开发笔记 > 编程语言 > 正文

在翻译LINQ表达式时,C#编译器如何选择SelectMany?

如何解决《在翻译LINQ表达式时,C#编译器如何选择SelectMany?》经验,为你挑选了2个好方法。

Enumerable.SelectMany有4个重载签名.为简单起见,我们忽略了带有int参数的两个签名.所以我们有4个SelectMany签名:

public static IEnumerable SelectMany(
    this IEnumerable source,
    Func> selector
)

public static IEnumerable SelectMany(
    this IEnumerable source,
    Func> collectionSelector,
    Func resultSelector
)

我的问题是:在将LINQ表达式转换为扩展方法调用时,C#编译器如何选择SelectMany?

基本上,如果LINQ表达式中有多个from,则会有SelectMany.但是,似乎C#编译器只选择第二个签名.永远不会使用第一个签名.

        IEnumerable en1 = Enumerable.Range(1, 3);
        IEnumerable en2 = new double[] { 1.0, 3.14 };

        IEnumerable en3 =
            from i1 in en1
            from i2 in en2
            select (i1 * i2).ToString();

        foreach (var i in en3)
        {
            Console.WriteLine(i);
        }

在Reflector的帮助下,我可以看到上面的LINQ表达式被翻译成了

en1.SelectMany(delegate (int i1) {
        return en2;
    }, delegate (int i1, double i2) {
        double CS$0$0000 = i1 * i2return CS$0$0000.ToString();
    })

以上示例涉及3种类型.因此,选择第二个SelectMany签名是合理的.但是,对于下面的示例,仅涉及一种类型,它仍然选择第二个签名.

        IEnumerable en4 =
            from i1 in en1
            from i2 in Enumerable.Range(0, i1)
            select i2;

它被翻译成:

en1.SelectMany(delegate (int i1) {
        return Enumerable.Range(0, i1);
    }, delegate (int i1, int i2) {
        return i2;
    })

所以,我找不到将LINQ表达式转换为第一个SelectMany签名的情况.有这种情况吗?

如果没有使用第一个SelectMany签名,那么它的存在只是因为它在函数式编程中是monad的BIND?

也许问题可能是:为什么我们有2个SelectMany签名?

谢谢.



1> JaredPar..:

根据C#Spec,编译器不会生成对第一版SelectMany的重载调用.SelectMany的第一个版本可用于将列表列表展平为单个平面列表.

public IEnumerable Example(IEnumerable> enumerable) {
  return enumerable.SelectMany(x => x);
}

它在查询表达式中没有强大的等价物.

有关详细信息,请参阅C#语言规范的第7.15.2节.



2> Amy B..:

为什么我们有2个SelectMany签名?

所以我可以在我的代码中使用第一个.

var orders = Customers.SelectMany(c => c.Orders)


SelectMany的第一个签名与monadic"bind"运算符同构,在Haskell中写成>> =.其中一个原因就是在完善的monad框架上巩固LINQ的基础.这个基础使LINQ可以多态地应用于各种事物,如可组合状态传播,异常,延续,替代等等:所有monad.见http://en.wikipedia.org/wiki/Monad_(functional_programming).
推荐阅读
wurtjq
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有