翻译LINQ表达式时,如何C#编译器选择的SelectMany? [英] How C# Compiler choose SelectMany when translating LINQ expression?

查看:258
本文介绍了翻译LINQ表达式时,如何C#编译器选择的SelectMany?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有4 Enumerable.SelectMany超载签名。为简单起见,我们忽略了两个签名与 INT 的参数。因此,我们有2个签名的SelectMany:

There are 4 overloaded signatures for Enumerable.SelectMany. To make it simple, we ignore the two signatures with int argument. So we have 2 signatures for 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
)

我的问题是:C#编译器翻译LINQ表达式来扩展方法调用的时候怎么选择的SelectMany ?

My question is: how C# compiler choose SelectMany when translating LINQ expression to extension method invocation?

基本上,如果有多个在LINQ表达后,会出现的SelectMany。但是,似乎C#编译器只能选择第二个签名。 。第一个签名是从未使用过

Basically, if there are multiple from in LINQ expression, there will be SelectMany. But, it seems that C# compiler only choose the second signature. The first signature is never used.

        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);
        }

通过反射镜的帮助下,我可以看到,上面的LINQ表达式被翻译成

With the help of Reflector, I can see that above LINQ expression is translated into

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();
    })

上面的例子中包括3种类型。所以,这是合理的选择第二的SelectMany签名。然而,例如下面,只有一种类型的受影响,则仍然选择第二签名

Above example involves 3 types. So, it is reasonable to select the second SelectMany signature. However, for below example, only one type is involved, it still selects the second signature.

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



它被翻译成:

It is translated into:

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

所以,我不能发现LINQ表达式被转换为第一的SelectMany签名的情况。有没有这样的情况?

So, I cannot find a case that LINQ expression is translated into the first SelectMany signature. Is there such case?

如果不使用第一的SelectMany签名,那么它的存在只是因为它是单子的BIND在函数式编程?

If the first SelectMany signature is not used, then it exists just because it is BIND of monad in functional programming?

也许这个问题可以是:为什么我们的SelectMany的

Perhaps the question can be: why do we have 2 signatures of SelectMany?

感谢

推荐答案

据C#的规格,编译器不会产生过载调用的的SelectMany的第一个版本。中的SelectMany第一个版本是扁平列表的列表成一个平坦的列表非常有用。

According to the C# Spec, the compiler will not generate an overload call to the first version of SelectMany. The first version of SelectMany is useful for flattening a List of Lists into a single flat list.

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



它不必在查询表达式强烈当量。

It doesn't have a strong equivalent in a query expression.

请参阅C#语言规范的7.15.2节以获取更多信息。

See Section 7.15.2 of the C# Language Spec for more information.

这篇关于翻译LINQ表达式时,如何C#编译器选择的SelectMany?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆