views:

309

answers:

6

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?

+1  A: 

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.

Yacoder
+33  A: 

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

Brandon
It might be nice if they produced a compiler warning about it though. I think that would be valuable.
Nick
+1 Nice complete answer, from an "official" source.
auujay
Makes sense . . . is it safe to say though that it's probably never a *good idea* to deliberately make a recursive property getter, as it would only ever stop if there were side effects, and (if I understand correctly) methods are preferred to properties in cases where there are side effects?
Tim Goodman
@Tim: Those side effects might be internal side effects that are generally , user-invisible side effects. It is not completely impossible for a property getter to have a side effect (e.g. if you want to keep count of how many times the get was called). OK, it's still pretty stupid :)
Brian
@Nick A lot of shops pretty are pretty strict about not allowing anything to compile with a warning, so they're pretty stringent about producing warnings for things that may not need them. See http://blogs.msdn.com/ericlippert/archive/2010/01/25/why-are-unused-using-directives-not-a-warning.aspx
Tanzelax
@Tanzelax - True, but I find the example in the link you referenced odd, since they explicitly mentioned "useless code" as not being worthy of a warning, yet they produce a warning "The field foo is never used" if you create a member variable foo which you never assign to.
Nick
@Nick: Eric posted another answer in this thread that basically addresses that. "the code is valid code... But since this is nonsensical code, you probably didn't mean to do it." You could probably just ask him about it right over there. :)
Tanzelax
A: 

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).

SLaks
+6  A: 

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.

dbkk
A: 

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.

Vlad
+5  A: 

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 its 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.

Eric Lippert
I was discussing this the comments on Alex's answer. Your statement that "But since this is nonsensical code, you probably didn't mean to do it. Since its not going to die horribly, we give a warning that there's something here that you probably didn't intend" seems to contradict your blog posting here: http://blogs.msdn.com/ericlippert/archive/2010/01/25/why-are-unused-using-directives-not-a-warning.aspx
Nick
@Nick: I'm not seeing the contradiction. (That doesn't mean there isn't one: I am large, I contain multitudes.) I'm just not seeing what you're getting at.
Eric Lippert
@Eric Lippert: Thank you for the Song of Myself reference. :-)
Jason
Thanks for both answers, Eric (this and my question this morning about how to pronounce your name.) For what it's worth, your position seems consistent to me. You write "we try to reserve warnings for only those situations where we can say with almost certainty that the code is broken, misleading or useless". `this.customerId = this.customerId` is undeniably useless.
Tim Goodman
@Eric - I just found the usings example in that post to be odd. It's certainly useless, and yet you don't warn about it (though I agree I wouldn't want that warning). But the "useless" code is also not a bug (by my estimation). Useless code is not incorrect code, and doesn't cause the software to behave incorrectly. I'm probably parsing all this too precisely.
Nick
@Nick: But as he says in that case it's *automatically generated* useless code . . . and causing it not to be automatically generated would be a nuisance when it's *not* useless.
Tim Goodman
@Nick: The difference between the two situations is that in the "unused using" example, the unused using is probably just fluff. It has no meaning whatsoever, it was never intended to have meaning, and it can be removed or kept without making a semantic change. The "assign variable to self" warning was almost certainly *intended to say something else*. We're not merely pointing out that the code is useless, we're pointing out that the code is *likely intended to be purposeful but in fact is useless*, the combination of which is highly likely to be a bug.
Eric Lippert
No... I get it. I'm just one of those guys who really like it when the compiler watches my back. Here is a compiler warning situation in VB.NET that has always gotten my goat http://stackoverflow.com/questions/2337835/no-warning-in-vb-net-when-function-has-no-return
Nick
Walter Bright is also vocally against warnings for code that "crashes loudly". This is why the D programming language doesn't have a NullPointerException.
Robert Fraser