2010-02-25 11 views
32

Wenn ich das bekomme ich ein System.StackOverflowException:Warum hält der C# -Compiler die Eigenschaften nicht davon ab, auf sich selbst zu verweisen?

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

Ich verstehe, warum - die Immobilie selbst verweist, zu einer Endlosschleife führt. (Siehe vorherige Fragen here und here).

Was ich frage mich (und was ich nicht in den vorherigen Fragen beantwortet sah) ist, warum nicht der C# -Compiler diesen Fehler? Es sucht nach anderen Arten von Zirkelverweisen (Klassen, die von sich selbst erben usw.), richtig? Ist es nur so, dass dieser Fehler nicht üblich genug war, um es zu überprüfen? Oder gibt es eine Situation, an die ich nicht denke, wenn Sie möchten, dass sich eine Immobilie auf diese Weise referenziert?

+2

Mit "sich selbst referenzieren", nehme ich an, ich möchte wirklich sagen "rekursiv sich selbst nennen", aber Sie bekommen die Idee. –

Antwort

42

Sie können den "offiziellen" Grund in der letzten Anmerkung here sehen.

Geschrieben von Microsoft am 14.11.2008 um 19:52

Danke für die Anregung für Visual Studio!

Sie sind richtig, dass wir könnten leicht Eigenschaft Rekursion erkennen, aber wir kann nicht garantieren, dass es nichts nützlich durch die Rekursion erreicht wird. Der Körper der Eigenschaft könnte gesetzt andere Felder auf Ihrem Objekt , die das Verhalten der nächsten Rekursion zu ändern, könnte sein Verhalten von der Konsole basierend auf Benutzereingaben ändern, oder könnte sogar anders basierend auf Zufallswerte verhalten. In diesen Fällen könnte eine selbstrekursive Eigenschaft in der Tat die Rekursion beenden, aber wir haben keine Möglichkeit festzustellen, ob das der Fall ist zur Kompilierzeit (ohne die Lösung Stoppt Problem!).

Aus den genannten Gründen (und der Änderung brechen sie dies nicht zulassen nehmen würde), würden wir nicht in der Lage sein zu verbieten Selbst rekursiven Eigenschaften.

Alex Turner

Program Manager

Visual C# Compiler

+20

Es könnte nett sein, wenn sie eine Compiler-Warnung darüber erzeugt haben. Ich denke, das wäre wertvoll. – Nick

+0

+1 Schöne vollständige Antwort von einer "offiziellen" Quelle. – auujay

+0

Macht Sinn. . . Es ist jedoch sicher, dass es wahrscheinlich nie eine gute Idee ist, absichtlich einen rekursiven Property-Getter zu machen, da dieser nur immer aufhört, wenn es Nebenwirkungen gibt, und (wenn ich das richtig verstehe) Methoden den Eigenschaften in Fällen vorgezogen werden Es gibt Nebenwirkungen? –

1

Sie hielten es wahrscheinlich für unnötig, den Compiler ohne wirklichen Gewinn zu komplizieren.

Sie werden diesen Tippfehler leicht entdecken, wenn Sie diese Eigenschaft das erste Mal nennen.

0

Die anderen Fälle Fälle, dass sie überprüft, für (außer rekursive Konstruktor) sind ungültig IL.
Darüber hinaus sind alle diese Fälle, sogar rekursive Konstruktoren) garantiert fehlgeschlagen.

Es ist jedoch möglich, wenn auch unwahrscheinlich, absichtlich eine nützliche rekursive Eigenschaft (unter Verwendung von if Anweisungen) zu erstellen.

9

Auf sich selbst bezogene Eigenschaft führt nicht immer zu unendlicher Rekursion und Stapelüberlauf. Zum Beispiel funktioniert das gut:

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

Above ein Dummy-Beispiel ist, aber ich bin sicher, dass man mit nützlichem rekursiven Code kommen könnte, die ähnlich ist. Der Compiler kann nicht feststellen, ob eine unendliche Rekursion auftritt (Problem anhalten).

Die Erstellung einer Warnung im einfachen Fall wäre hilfreich.

1

Als Erstes erhalten Sie eine Warnung für die nicht verwendete Variable abc.

Zweitens gibt es nichts Schlimmes in der Rekursion, vorausgesetzt es ist keine endlose Rekursion. Zum Beispiel könnte der Code einige innere Variablen anpassen und dann den gleichen Getter rekursiv aufrufen. Es gibt jedoch für den Compiler keinen einfachen Weg, zu beweisen, dass eine Rekursion endlos ist oder nicht (die Aufgabe ist zumindest NP). Der Compiler könnte einige einfache Fälle auffangen, aber dann wären die Verbraucher überrascht, dass die komplizierteren Fälle die Compiler-Prüfungen durchlaufen.

11

Ein weiterer Punkt neben Alex Erklärung ist, dass wir versuchen, Warnungen für Code, der etwas tut, was Sie wahrscheinlich nicht beabsichtigten, so, dass Sie versehentlich mit dem Fehler versenden können.

Wie lange würde die Warnung tatsächlich in diesem Fall speichern? Ein einzelner Testlauf. Sie werden diesen Fehler in dem Moment finden, in dem Sie den Code testen, weil er immer sofort abstürzt und schrecklich stirbt. Die Warnung würde Ihnen hier eigentlich keinen großen Vorteil bringen. Die Wahrscheinlichkeit, dass ein Fehler in einer rekursiven Eigenschaftsevaluation ist, ist gering.

dagegen wir tun eine Warnung ausgeben, wenn Sie so etwas tun:

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

Es gibt keine schrecklichen Crash-und-sterben, und der Code ist gültig Code; Es weist einem Feld einen Wert zu. Aber da dies ein unsinniger Code ist, wollten Sie es wahrscheinlich nicht machen. Da es nicht fürchterlich sterben wird, warnen wir, dass hier etwas ist, was Sie wahrscheinlich nicht vorhatten und sonst nicht durch einen Absturz entdecken könnten.

+0

Ich diskutierte das die Kommentare zu Alex 'Antwort. Ihre Aussage "Aber da dies unsinniger Code ist, wollten Sie es wahrscheinlich nicht tun. Da es nicht schrecklich sterben wird, warnen wir davor, dass hier etwas ist, was Sie wahrscheinlich nicht vorhatten" scheint Ihrem Blog zu widersprechen hier posten: http://blogs.msdn.com/ericlippert/archive/2010/01/25/why-are-unused-using-directives-not-a-warning.aspx – Nick

+1

@Nick: Ich sehe nicht die Widerspruch. (Das heißt nicht, dass es nicht einen gibt: Ich bin groß, ich habe eine Menge.) Ich sehe einfach nicht, worauf du hinauswillst. –

+0

@Eric Lippert: Danke für das Lied von mir selbst Referenz. :-) – jason

Verwandte Themen