Подтвердить что ты не робот

Почему компилятор С# не останавливает свойства от ссылки на себя?

Если я сделаю это, я получу System.StackOverflowException:

private string abc = "";
public string Abc
{
    get
    { 
        return Abc; // Note the mistaken capitalization
    }
}

Я понимаю, почему - свойство ссылается на себя, что приводит к бесконечному циклу. (См. Предыдущие вопросы здесь и здесь).

Что мне интересно (и что я не видел в ответах на предыдущие вопросы), почему компилятор С# не поймает эту ошибку? Он проверяет некоторые другие виды циркулярной ссылки (классы, наследующие от себя и т.д.), Правильно? Это просто, что эта ошибка не была достаточно распространена, чтобы заслужить проверку? Или есть какая-то ситуация, о которой я не думаю, когда вы хотите, чтобы свойство действительно ссылалось на себя таким образом?

4b9b3361

Ответ 1

Вы можете увидеть "официальную" причину в последнем комментарии здесь.

Отправлено Microsoft 14/11/2008 в 19:52

Спасибо за предложение Visual Studio!

Вы правы, что могли бы легко определить рекурсию свойств, но мы не может гарантировать, что нет ничего полезный, выполняемый рекурсии. Тело собственности может устанавливать другие поля на вашем объекте которые меняют поведение следующего рекурсия, может изменить свое поведение основанный на пользовательском вводе с консоли, или могут даже вести себя по-разному по случайным значениям. В этих случаях саморекурсивное свойство действительно может прекратите рекурсию, но у нас есть нет способа определить, является ли это случай во время компиляции (без решения проблема с остановкой!).

По причинам выше (и что запретите это), мы не сможем запретить саморекурсивные свойства.

Алекс Тернер

Менеджер программ

Компилятор Visual С#

Ответ 2

Другим моментом в дополнение к объяснению Alex является то, что мы пытаемся дать предупреждения для кода, который делает то, что вы, вероятно, не намеревались, , чтобы вы случайно могли отправить с ошибкой.

В этом конкретном случае, сколько времени предупреждение действительно спасет вас? Один тестовый прогон. Вы обнаружите эту ошибку в тот момент, когда вы проверите код, потому что он всегда сразу падает и умирает ужасно. Предупреждение на самом деле не принесло бы вам большой пользы здесь. Вероятность того, что есть некоторая тонкая ошибка в оценке рекурсивного свойства, низкая.

В отличие от этого, мы делаем предупреждение, если вы делаете что-то вроде этого:

int customerId; 
...
this.customerId= this.customerId;

Там нет ужасной аварии и смерти, и код является действительным кодом; он присваивает значение полю. Но поскольку это бессмысленный код, вы, вероятно, не хотели этого делать. Поскольку он не собирается умирать ужасно, мы предупреждаем, что здесь есть что-то, что вы, вероятно, не намеревались и не могли бы иначе обнаружить через крушение.

Ответ 3

Свойство, ссылающееся на себя, не всегда приводит к бесконечной рекурсии и переполнению стека. Например, это отлично работает:

int count = 0;
public string Abc
{
    count++;
    if (count < 1) return Abc;
    return "Foo";
}

Выше - фиктивный пример, но я уверен, что можно найти полезный рекурсивный код, похожий. Компилятор не может определить, произойдет ли бесконечная рекурсия (проблема с остановкой).

Было бы полезно создать предупреждение в простом случае.

Ответ 4

Вероятно, они считали, что это не будет усложнять компилятор без какого-либо реального выигрыша.

Вы легко обнаружите эту опечатку при первом вызове этого свойства.

Ответ 5

Прежде всего, вы получите предупреждение о неиспользуемой переменной abc.

Во-вторых, нет ничего плохого в рекурсии, при условии, что это не бесконечная рекурсия. Например, код может корректировать некоторые внутренние переменные, а рекурсивно вызывать один и тот же геттер. Однако для компилятора вообще нет простого способа доказать, что некоторая рекурсия бесконечна или нет (задача, по крайней мере, NP). Компилятор мог поймать несколько простых случаев, но тогда потребители были бы удивлены тем, что более сложные случаи проходят через проверки компилятора.

Ответ 6

Другие случаи, которые он проверяет (кроме рекурсивного конструктора), недействительны. IL. Кроме того, все эти случаи, даже рекурсивные конструкторы) гарантированно терпят неудачу.

Однако возможно, хотя и маловероятно, намеренно создать полезное рекурсивное свойство (используя операторы if).