Попробуйте скомпилировать следующий код, и вы обнаружите, что компилятор занимает> 3 ГБ ОЗУ (вся свободная память на моем компьютере) и очень много времени для компиляции (на самом деле я получаю исключение ввода-вывода через 10 минут).
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)))))));
}
}
Кто-нибудь может объяснить это любопытное поведение?
Версия CS: Microsoft (R) Visual C # Compiler версии 4.0.30319.17929 Имя ОС: Microsoft Windows 7 Ultimate. Версия ОС: 6.1.7601, пакет обновления 1, сборка 7601
Ответы:
Я считаю, что это связано с выводом типа и / или генерацией лямбда (когда вывод типа должен идти в направлении, противоположном нормальному) в сочетании с разрешением перегрузки. К сожалению, простая передача параметров типа не помогает в ситуации (где, по-видимому, все еще необходимо выполнить проверку типа).
Следующий код, который логически должен быть эквивалентом вашего кода, после анализа лямбда-выражений компилируется без проблем:
Я считаю, что Эрик Липперт опубликовал сообщение до того, что вывод типа является одним из тех мест в компиляторе C #, где (определенные проблемы) могут заставить компилятор попытаться решить проблему NP-Complete, и его единственная реальная стратегия (как здесь) - это грубая сила. Если я найду соответствующие ссылки, я добавлю их сюда.
Лучшая ссылка, которую я могу найти, - это здесь, где Эрик обсуждает тот факт, что именно работа по разрешению перегрузки вызывает реальные затраты - помните, Enumerable.Sum имеет 10 перегрузок, которые принимают лямбда / метод.
источник
10^n
комбинации (гдеn
- количество связанных методов). Звучит разумно (то есть в качестве объяснения).that^numberofpossibletypes