Я виходжу на ноги, публікуючи це, але я думаю, що відповідь така:
Між 550 і 575 роками
із налаштуваннями за замовчуванням у Visual Studio 2015
Я створив невелику програму, яка генерує вкладені for
цикли ...
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);
}
}
...
...
}
}
Для 500 вкладених циклів програму все ще можна скомпілювати. Маючи 575 петель, компілятор рятує:
Попередження Аналізатор AD0001 'Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames.CSharpSimplifyTypeNamesDiagnosticAnalyzer' викинув виняток типу 'System.InsufficientExecutionStackException' із повідомленням 'Недостатній стек для подальшого виконання програми. Це може статися через занадто багато функцій у стеку викликів або функцій у стеку, використовуючи занадто багато місця в стеці. '.
з основним повідомленням компілятора
помилка CS8078: Вираз занадто довгий або складний для компіляції
Звичайно, це чисто гіпотетичний результат. Якщо внутрішній цикл робить більше, ніж a Console.WriteLine
, то може бути можливо менше вкладених циклів до перевищення розміру стека. Крім того, це може бути не суворо технічним обмеженням, у тому сенсі, що можуть бути приховані налаштування для збільшення максимального розміру стека для "Аналізатора", який згадується в повідомленні про помилку, або (за необхідності) для отриманого виконуваного файлу. Однак ця частина відповіді залишається за людьми, які глибоко знають С #.
Оновлення
У відповідь на запитання в коментарях :
Мені було б цікаво побачити, як цю відповідь розширили, щоб експериментально "довести", чи можна помістити 575 локальних змінних у стек, якщо вони не використовуються у циклах for-for, та / чи можна розмістити 575 невкладених for-циклів у одна функція
В обох випадках відповідь така: так, це можливо. При заповненні методу 575 автоматично згенерованих операторів
int i0=0;
Console.WriteLine(i0);
int i1=0;
Console.WriteLine(i1);
...
int i574=0;
Console.WriteLine(i574);
його ще можна скомпілювати. Все інше мене здивувало б. Розмір стека, необхідний для int
змінних, становить лише 2,3 КБ. Але мені було цікаво, і для того, щоб перевірити подальші обмеження, я збільшив цю кількість. Зрештою, він не скомпілювався, спричинивши помилку
помилка CS0204: Дозволено лише 65534 місцевих жителів, у тому числі створених компілятором
що є цікавим моментом, але це вже спостерігалося в інших місцях: Максимальна кількість змінних у методі
Подібним чином, 575 невкладених - for
циклів, як у
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);
}
також можна скомпілювати. Тут я також спробував знайти межу і створив більше цих циклів. Зокрема, я не був впевнений, чи змінні циклу в цьому випадку також враховують усіх "місцевих жителів", оскільки вони є своїми { block }
. Але все-таки більше 65534 неможливо. Нарешті, я додав тест, що складається з 40000 петель візерунка
for (int i39999 = 0; i39999 < 10; i39999++)
{
int j = 0;
Console.WriteLine(j + i39999);
}
який містив додаткову змінну в циклі, але, схоже, вони також вважаються "місцевими", і скомпілювати це не вдалося.
Отже, підсумовуючи: Межа ~ 550 справді обумовлена глибиною вкладеності петель. На це також вказувало повідомлення про помилку
помилка CS8078: Вираз занадто довгий або складний для компіляції
Документації CS1647 помилок , до жаль (але по зрозумілих причин ) не визначає «вимірювання» складності, але дає тільки прагматичний рада
У компіляторі, який обробляє ваш код, було переповнення стека. Щоб вирішити цю помилку, спростіть свій код.
Щоб ще раз наголосити на цьому: для for
приватного випадку глибоко вкладених циклів все це досить академічно та гіпотетично . Але веб-пошук повідомлення про помилку CS1647 виявляє кілька випадків, коли ця помилка з'являлася для коду, який, швидше за все, не був навмисно складним, але створювався в реалістичних сценаріях.