Почему компилятор C # не мешает свойствам ссылаться на себя? - PullRequest
34 голосов
/ 25 февраля 2010

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

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

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

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

Ответы [ 6 ]

44 голосов
/ 25 февраля 2010

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

Опубликовано Microsoft 14/11/2008 в 19:52

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

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

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

Алекс Тернер

Диспетчер программ

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

13 голосов
/ 25 февраля 2010

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

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

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

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

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

10 голосов
/ 25 февраля 2010

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

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

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

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

1 голос
/ 25 февраля 2010

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

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

1 голос
/ 25 февраля 2010

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

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

0 голосов
/ 25 февраля 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...