Как создать необнаружимый бесконечный цикл? - PullRequest
13 голосов
/ 22 февраля 2010

Это просто вопрос "Мне любопытно".

В C # подробно Джон Скит говорит о лямбда-выражениях:
"если существует недействительный тип возврата, каждый путь кода должен возвращать совместимое значение." (стр. 233)

Затем в сноске говорится:
"Конечно, пути кода, генерирующие исключения, не должны возвращать значение, и также не обнаруживаются бесконечные циклы." (Страница 233)

Мне интересно, что представляет собой необнаружимый бесконечный цикл?

Может ли это быть сделано только логикой? или это делается с помощью внешних факторов, таких как база данных или файловая система?

Ответы [ 2 ]

21 голосов
/ 22 февраля 2010

То, на что ссылается Джон, описано в разделе 8.1 спецификации. Компилятор может обнаруживать только очень простые бесконечные циклы, например:

while(true) { if (0 != 0) return 123; }

Компилятор достаточно умен, чтобы видеть, что возвращение никогда не достигается, и, следовательно, цикл работает вечно. Законно, хотя и безумно, сказать:

int M() { while(true) { } }

потому что, хотя нет пути, который возвращает int, также нет пути, который возвращает без , возвращающего int!

Компилятор недостаточно умен, чтобы найти другие виды бесконечных циклов. Например:

int x = 123;
while(true) { if (x * 0 != 0) break; }

Это явно бесконечный цикл. Но компилятор этого не знает. Компилятор говорит: «Ну, может быть, есть какое-то значение x, где x * 0 не равно нулю, поэтому разрыв достижим, поэтому это не бесконечный цикл». Мы с тобой знаем, что это невозможно, потому что мы знаем математику, а компилятор - нет.

Прочтите раздел 8.1, если хотите узнать подробности.

3 голосов
/ 22 февраля 2010

Довольно просто создать бесконечный цикл, используя внешние источники или даже используя инструменты, такие как интерфейсы.

Например:

  public interface INumbers
    {
        int GetNumber(int arg);
    }
    public class StaticNumber : INumbers
    {
        public int GetNumber(int arg)
        {
            return 1;
        }
    }
    public void DoStuff(INumbers num)
    {
        int i = 42;
        while ((i = num.GetNumber(i)) != 0)
        {
            ;
        }
    }

, а затем простой

Action action = () => DoStuff(new StaticNumber());
...