简体   繁体   English

为什么C#编译器会对这个嵌套的LINQ查询感到厌烦?

[英]Why does the C# compiler go mad on this nested LINQ query?

Try to compile following code and you'll find that compiler takes >3 GB of RAM (all free memory on my machine) and very long time to compile (actually I get IO exception after 10 minutes). 尝试编译以下代码,你会发现编译器需要> 3 GB的RAM(我机器上的所有可用内存)和很长的编译时间(实际上我在10分钟后得到IO异常)。

using System;
using System.Linq;

public class Test
{
    public static void Main()
    {
        Enumerable.Range(0, 1).Sum(a =>
        Enumerable.Range(0, 1).Sum(b =>
        Enumerable.Range(0, 1).Sum(c =>
        Enumerable.Range(0, 1).Sum(d =>
        Enumerable.Range(0, 1).Sum(e =>
        Enumerable.Range(0, 1).Sum(f =>
        Enumerable.Range(0, 1).Count(g => true)))))));
    }
}

Can anybody explain this curious behavior? 任何人都可以解释这种奇怪的行为吗?

CS Version:     Microsoft (R) Visual C# Compiler version 4.0.30319.17929
OS Name:        Microsoft Windows 7 Ultimate
OS Version:     6.1.7601 Service Pack 1 Build 7601

内存使用情况

I believe that it's related to type inference and/or lambda generation (when type inference has to go in the opposite direction to normal), combined with overload resolution. 我相信它与类型推断和/或lambda生成有关(当类型推断必须与正常方向相反时),结合重载决策。 Unfortunately, just supplying the type parameters doesn't help the situation (where it presumably still has to perform the type checking). 不幸的是,只提供类型参数对情况没有帮助(它可能仍然需要执行类型检查)。

The following code, which should logically be the equivalent code from yours, after lambdas have been analyzed, compiles without issue: 在分析了lambdas之后,以下代码在逻辑上应该是您的等效代码,编译没有问题:

static void Main()
{
    var x = Enumerable.Range(0, 1).Sum(a);
}

private static int a(int a)
{
    return Enumerable.Range(0, 1).Sum(b);
}
private static int b(int b)
{
    return Enumerable.Range(0, 1).Sum(c);
}
private static int c(int c)
{
    return Enumerable.Range(0, 1).Sum(d);
}
private static int d(int d)
{
    return Enumerable.Range(0, 1).Sum(e);
}
private static int e(int e)
{
    return Enumerable.Range(0, 1).Sum(f);
}
private static int f(int f)
{
    return Enumerable.Range(0, 1).Count(g);
}
private static bool g(int g)
{
    return true;
}

I believe Eric Lippert has posted before that type inference is one of the places in the C# compiler where (certain problems) may force the compiler to try to solve an NP-Complete problem and its only real strategy (as here) is brute force. 我相信Eric Lippert之前发布的类型推断是C#编译器中的一个地方,其中(某些问题)可能会迫使编译器尝试解决NP-Complete问题,而其唯一真正的策略(如此处)是强力的。 If I can find the relevant references, I'll add them here. 如果我能找到相关的参考文献,我会在这里添加它们。


The best reference I can find is here where Eric's discussing the fact that it's the overload resolution work that causes the real cost - remember, Enumerable.Sum has 10 overloads that accept a lambda/method. 我能找到的最好的参考就是这里埃里克的讨论事实上,它是重载解析的工作,使真正的成本-记住, Enumerable.Sum有10个重载接受一个lambda /方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM