Wychodzę na skraj, publikując to, ale myślę, że odpowiedź brzmi:
Między 550 a 575
z ustawieniami domyślnymi w programie Visual Studio 2015
Stworzyłem mały program, który generuje zagnieżdżone for
pętle ...
for (int i0=0; i0<10; i0++)
{
for (int i1=0; i1<10; i1++)
{
...
...
for (int i573=0; i573<10; i573++)
{
for (int i574=0; i574<10; i574++)
{
Console.WriteLine(i574);
}
}
...
...
}
}
W przypadku 500 zagnieżdżonych pętli program można nadal skompilować. W przypadku pętli 575 kompilator wyskakuje:
Ostrzeżenie Analizator AD0001 „Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames.CSharpSimplifyTypeNamesDiagnosticAnalyzer” zgłosił wyjątek typu „System.InsufficientExecutionStackException” z komunikatem „Niewystarczający stos, aby kontynuować bezpieczne wykonywanie programu. Może się tak zdarzyć, gdy na stosie wywołań znajduje się zbyt wiele funkcji lub funkcja na stosie zajmuje zbyt dużo miejsca. '.
z podstawowym komunikatem kompilatora
błąd CS8078: Wyrażenie jest zbyt długie lub złożone, aby można było je skompilować
Oczywiście jest to czysto hipotetyczny wynik. Jeśli najbardziej wewnętrzna pętla robi więcej niż a Console.WriteLine
, to mniej zagnieżdżonych pętli może być możliwych, zanim rozmiar stosu zostanie przekroczony. Może to również nie być ściśle techniczne ograniczenie w tym sensie, że mogą istnieć ukryte ustawienia zwiększające maksymalny rozmiar stosu dla „Analizatora”, o którym mowa w komunikacie o błędzie, lub (jeśli to konieczne) dla wynikowego pliku wykonywalnego. Jednak ta część odpowiedzi jest pozostawiona osobom, które dogłębnie znają język C #.
Aktualizacja
W odpowiedzi na pytanie w komentarzach :
Chciałbym zobaczyć tę odpowiedź rozwiniętą, aby "udowodnić" eksperymentalnie, czy możesz umieścić 575 zmiennych lokalnych na stosie, jeśli nie są one używane w pętlach for i / lub czy możesz umieścić 575 niezagnieżdżonych pętli for w pojedyncza funkcja
W obu przypadkach odpowiedź brzmi: tak, jest to możliwe. Podczas wypełniania metody 575 automatycznie wygenerowanymi wyciągami
int i0=0;
Console.WriteLine(i0);
int i1=0;
Console.WriteLine(i1);
...
int i574=0;
Console.WriteLine(i574);
nadal można go skompilować. Wszystko inne by mnie zaskoczyło. Rozmiar stosu wymagany dla int
zmiennych to zaledwie 2,3 KB. Ale byłem zaciekawiony i aby sprawdzić dalsze ograniczenia, zwiększyłem tę liczbę. Ostatecznie nie skompilował się, powodując błąd
błąd CS0204: Dozwolone są tylko 65534 lokalizacje lokalne, w tym te wygenerowane przez kompilator
co jest interesujące, ale zostało już zaobserwowane gdzie indziej: Maksymalna liczba zmiennych w metodzie
Podobnie, 575 zagnieżdżane for
-loops, jak w
for (int i0=0; i0<10; i0++)
{
Console.WriteLine(i0);
}
for (int i1=0; i1<10; i1++)
{
Console.WriteLine(i1);
}
...
for (int i574=0; i574<10; i574++)
{
Console.WriteLine(i574);
}
można również skompilować. Tutaj również próbowałem znaleźć limit i utworzyłem więcej tych pętli. W szczególności nie byłem pewien, czy zmienne pętli w tym przypadku również liczą się jako „lokalne”, ponieważ są one same w sobie { block }
. Ale nadal więcej niż 65534 nie jest możliwe. Na koniec dodałem test składający się z 40000 pętli wzoru
for (int i39999 = 0; i39999 < 10; i39999++)
{
int j = 0;
Console.WriteLine(j + i39999);
}
który zawierał dodatkową zmienną w pętli, ale wydaje się, że są one również liczone jako „lokalne” i nie można było tego skompilować.
Podsumowując: granica ~ 550 jest rzeczywiście spowodowana głębokością zagnieżdżenia pętli. Wskazuje na to również komunikat o błędzie
błąd CS8078: Wyrażenie jest zbyt długie lub złożone, aby można było je skompilować
Dokumentacja błędów CS1647 niestety (ale ze zrozumiałych względów) nie określa „pomiar” złożoności, ale tylko daje pragmatyczne porady
W kompilatorze przetwarzającym kod wystąpiło przepełnienie stosu. Aby rozwiązać ten błąd, uprość kod.
Aby jeszcze raz to podkreślić: w szczególnym przypadku głęboko zagnieżdżonych for
pętli wszystko to jest raczej akademickie i hipotetyczne . Jednak wyszukiwanie w Internecie komunikatu o błędzie CS1647 ujawnia kilka przypadków, w których ten błąd pojawił się dla kodu, który najprawdopodobniej nie był celowo złożony, ale został utworzony w realistycznych scenariuszach.