Aufzählungszeichen können mehr als einmal ausgewertet werden
Es wird Sie beißen, wenn Sie eine lazily-enumerated enumerable haben und Sie iterieren über sie zweimal und erhalten unterschiedliche Ergebnisse. (oder Sie erhalten die gleichen Ergebnisse, aber es wird unnötigerweise zweimal ausgeführt)
Als ich zum Beispiel einen bestimmten Test schrieb, brauchte ich ein paar temporäre Dateien, um die Logik zu testen:
var files = Enumerable.Range(0, 5)
.Select(i => Path.GetTempFileName());
foreach (var file in files)
File.WriteAllText(file, "HELLO WORLD!");
/* ... many lines of codes later ... */
foreach (var file in files)
File.Delete(file);
Stellen Sie sich meine Überraschung vor, als File.Delete(file)
wirft FileNotFound
!!
Was hier passiert ist, dass die files
Aufzählung wurde iteriert zweimal (die Ergebnisse der ersten Iteration sind einfach no gemerkt) und bei jeder neuen Iteration würden Sie erneut Path.GetTempFilename()
so dass Sie einen anderen Satz von temporären Dateinamen erhalten.
Die Lösung besteht natürlich darin, den Wert eager-enumerate mit Hilfe von ToArray()
ou ToList()
:
var files = Enumerable.Range(0, 5)
.Select(i => Path.GetTempFileName())
.ToArray();
Dies ist noch beängstigender, wenn Sie etwas mit mehreren Threads machen, wie z. B.:
foreach (var file in files)
content = content + File.ReadAllText(file);
und Sie finden heraus content.Length
nach all den Schreibvorgängen immer noch 0 ist!! Sie fangen dann an, rigoros zu überprüfen, dass Sie keine Race Condition haben, wenn.... nach einer vergeudeten Stunde... Sie herausgefunden haben, dass es nur diese winzige kleine Enumerable gotcha Sache ist, die Sie vergessen haben....
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.