Why doesn't the C# compiler stop properties fr

2020-01-28 08:12发布

If I do this I get a System.StackOverflowException:

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

I understand why -- the property is referencing itself, leading to an infinite loop. (See previous questions here and here).

What I'm wondering (and what I didn't see answered in those previous questions) is why doesn't the C# compiler catch this mistake? It checks for some other kinds of circular reference (classes inheriting from themselves, etc.), right? Is it just that this mistake wasn't common enough to be worth checking for? Or is there some situation I'm not thinking of, when you'd want a property to actually reference itself in this way?

6条回答
Luminary・发光体
2楼-- · 2020-01-28 08:38

You can see the "official" reason in the last comment here.

Posted by Microsoft on 14/11/2008 at 19:52

Thanks for the suggestion for Visual Studio!

You are right that we could easily detect property recursion, but we can't guarantee that there is nothing useful being accomplished by the recursion. The body of the property could set other fields on your object which change the behavior of the next recursion, could change its behavior based on user input from the console, or could even behave differently based on random values. In these cases, a self-recursive property could indeed terminate the recursion, but we have no way to determine if that's the case at compile-time (without solving the halting problem!).

For the reasons above (and the breaking change it would take to disallow this), we wouldn't be able to prohibit self-recursive properties.

Alex Turner

Program Manager

Visual C# Compiler

查看更多
▲ chillily
3楼-- · 2020-01-28 08:38

They probably considered it would unnecessary complicate the compiler without any real gain.

You will discover this typo easily the first time you call this property.

查看更多
我欲成王,谁敢阻挡
4楼-- · 2020-01-28 08:42

First of all, you'll get a warning for unused variable abc.

Second, there is nothing bad in teh recursion, provided that it's not endless recursion. For example, the code might adjust some inner variables and than call the same getter recursively. There is however for the compiler no easy way at all to prove that some recursion is endless or not (the task is at least NP). The compiler could catch some easy cases, but then the consumers would be surprised that the more complicated cases get through the compiler's checks.

查看更多
Ridiculous、
5楼-- · 2020-01-28 08:46

Another point in addition to Alex's explanation is that we try to give warnings for code which does something that you probably didn't intend, such that you could accidentally ship with the bug.

In this particular case, how much time would the warning actually save you? A single test run. You'll find this bug the moment you test the code, because it always immediately crashes and dies horribly. The warning wouldn't actually buy you much of a benefit here. The likelihood that there is some subtle bug in a recursive property evaluation is low.

By contrast, we do give a warning if you do something like this:

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

There's no horrible crash-and-die, and the code is valid code; it assigns a value to a field. But since this is nonsensical code, you probably didn't mean to do it. Since it's not going to die horribly, we give a warning that there's something here that you probably didn't intend and might not otherwise discover via a crash.

查看更多
孤傲高冷的网名
6楼-- · 2020-01-28 08:46

The other cases cases that it checks for (except recursive constructor) are invalid IL.
In addition, all of those cases, even recursive constructors) are guarenteed to fail.

However, it is possible, albeit unlikely, to intentionally create a useful recursive property (using if statements).

查看更多
beautiful°
7楼-- · 2020-01-28 08:50

Property referring to itself does not always lead to infinite recursion and stack overflow. For example, this works fine:

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

Above is a dummy example, but I'm sure one could come up with useful recursive code that is similar. Compiler cannot determine if infinite recursion will happen (halting problem).

Generating a warning in the simple case would be helpful.

查看更多
登录 后发表回答