Spróbuj skompilować następujący kod, a zobaczysz, że kompilator zajmuje> 3 GB pamięci RAM (cała wolna pamięć na moim komputerze) i bardzo długi czas na kompilację (w rzeczywistości otrzymuję wyjątek IO po 10 minutach).
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)))))));
}
}
Czy ktoś może wyjaśnić to dziwne zachowanie?
Wersja CS: kompilator Microsoft (R) Visual C # w wersji 4.0.30319.17929 Nazwa systemu operacyjnego: Microsoft Windows 7 Ultimate Wersja systemu operacyjnego: 6.1.7601 z dodatkiem Service Pack 1, kompilacja 7601
Odpowiedzi:
Uważam, że jest to związane z wnioskiem o typie i / lub generowaniem lambda (gdy wnioskowanie o typie musi iść w przeciwnym kierunku do normalnego), w połączeniu z rozwiązywaniem przeciążenia. Niestety, samo podanie parametrów typu nie pomaga w sytuacji (w której prawdopodobnie nadal musi wykonać sprawdzenie typu).
Poniższy kod, który logicznie powinien być równoważnym kodem z twojego, po przeanalizowaniu lambd, kompiluje się bez problemu:
Uważam, że Eric Lippert opublikował wcześniej, że wnioskowanie o typie jest jednym z miejsc w kompilatorze C #, w którym (pewne problemy) mogą zmusić kompilator do próby rozwiązania problemu NP-Complete, a jego jedyną realną strategią (jak tutaj) jest brutalna siła. Jeśli znajdę odpowiednie referencje, dodam je tutaj.
Najlepsze odniesienie, jakie mogę znaleźć, jest tutaj, gdzie Eric omawia fakt, że to praca nad rozwiązywaniem przeciążenia powoduje rzeczywisty koszt - pamiętaj, Enumerable. ma 10 przeciążeń, które akceptują lambda / metodę.
źródło
10^n
kombinacje (gdzien
jest liczba połączonych metod). Brzmi rozsądnie (to znaczy jako wyjaśnienie).that^numberofpossibletypes