Das Heisenberg-Uhrenfenster
Das kann sich negativ auswirken, wenn Sie z. B. Load-on-demand-Sachen machen:
private MyClass _myObj;
public MyClass MyObj {
get {
if (_myObj == null)
_myObj = CreateMyObj(); // some other code to create my object
return _myObj;
}
}
Nehmen wir nun an, Sie haben an anderer Stelle einen Code, der dies verwendet:
// blah
// blah
MyObj.DoStuff(); // Line 3
// blah
Jetzt wollen Sie Ihr Debugging CreateMyObj()
Methode. Sie setzen also einen Haltepunkt in Zeile 3, mit der Absicht, in den Code einzugreifen. Vorsichtshalber setzen Sie auch einen Haltepunkt in der Zeile darüber, in der es heißt _myObj = CreateMyObj();
und sogar einen Haltepunkt innerhalb von CreateMyObj()
selbst.
Der Code trifft auf Ihren Haltepunkt in Zeile 3. Sie steigen in den Code ein. Sie erwarten, dass Sie den bedingten Code eingeben, denn _myObj
ist offensichtlich null, richtig? Äh... also... warum hat es die Bedingung übersprungen und ist direkt zu return _myObj
?! Sie fahren mit der Maus über _myObj... und tatsächlich, es hat einen Wert! Wie konnte das passieren?!
Die Antwort ist, dass Ihre IDE den Wert ermittelt hat, weil Sie ein "Watch"-Fenster geöffnet haben - insbesondere das "Autos"-Watch-Fenster, das die Werte aller Variablen/Eigenschaften anzeigt, die für die aktuelle oder vorherige Ausführungszeile relevant sind. Als Sie Ihren Haltepunkt in Zeile 3 erreichten, entschied das Überwachungsfenster, dass Sie den Wert von MyObj
- also hinter den Kulissen, einen Ihrer Haltepunkte zu ignorieren berechnet es den Wert von MyObj
für Sie - einschließlich der Aufforderung an CreateMyObj()
die den Wert von _myObj setzt!
Deshalb nenne ich es auch das Heisenbergsche Uhrenfenster - man kann den Wert nicht beobachten, ohne ihn zu beeinflussen... :)
GOTCHA!
Editer - Ich denke, der Kommentar von @ChristianHayter verdient es, in die Hauptantwort aufgenommen zu werden, da er eine wirksame Lösung für dieses Problem zu sein scheint. Also immer, wenn Sie eine Lazy-Loaded-Eigenschaft haben...
Schmücken Sie Ihre Eigenschaft mit [DebuggerBrowsable(DebuggerBrowsableState.Never)] oder [DebuggerDisplay("<auf Anfrage geladen>")] - Christian Hayter
158 Stimmen
Return DateTime.Now.AddDays(1);
24 Stimmen
Soweit ich weiß, sind die eingebauten Werttypen alle unveränderlich, zumindest insofern, als jede Methode, die mit dem Typ verbunden ist, ein neues Element zurückgibt, anstatt das vorhandene Element zu verändern. Zumindest fällt mir spontan kein Typ ein, der dies nicht tut: alles schön und konsistent.
1 Stimmen
Community-Wiki, so viel Spam in SO jetzt. Wenn Fragen subjektiv sind (keine endgültige Antwort), sollte es Community Wiki sein.
6 Stimmen
Veränderlicher Werttyp: System.Collections.Generics.List.Enumerator :( (Und ja, Sie können sehen, dass es sich seltsam verhält, wenn Sie sich genug Mühe geben).
0 Stimmen
Lol, ich wusste, dass es Ausnahmen geben würde. Enumerator scheint irgendwie... s
14 Stimmen
T
22 Stimmen
N
4 Stimmen
T
4 Stimmen
D
2 Stimmen
Sollte genannt werden
dt.NextDays(1);
haben die Programmierer keine Ahnung, dass er seinen eigenen Wert ändert. Genauso wie bei Datenstrukturkonstrukten (z.B.node->next
,node.next
) ändert den Wert von node nicht. Und jetzt ist es zu spät, sie könntendt.AddDays(1)
die Semantik, dass sie Tage in ihrem eigenen Wert hinzufügen.1 Stimmen
Ich stimme zu, dass es sich bei dem genannten Beispiel um eine Frage der Namensgebung handelt. Der Name der Methode impliziert, dass sie zum Datum addiert wird. Etwas wie
dt.PlusDays(1)
wäre klarer. Ein weiteres Problem bei dieser Methode ist, dass sie nur einedouble
Wert, so dass das Ergebnis nicht exakt ist.0 Stimmen
Ich würde diese Frage gewinnen, wenn eine dumme Person dieses Thema nicht geschlossen hätte. Ich kenne den bösesten Bug der Welt. Bitte sehen Sie codeproject.com/Feature/
1 Stimmen
@bluefeet, da die Benutzer >= 62 Antworten gegeben haben (einschließlich Jon Skeet), viele davon mit Hunderten von Bewertungen, dann wollen die Benutzer offenbar auch diese Art von Fragen. Entweder handelt es sich hier um eine angemessene Art von Fragen, oder es ist Zeit für eine Verfassungsänderung aller einschränkenden Regeln von SO.
0 Stimmen
5.add(2); 5 sollte immer noch 5 sein.