可枚举对象可以被多次评估
当你迭代一个惰性枚举的可枚举对象两次并获得不同的结果时,它会使你犯错。(或者你会获得相同的结果,但会不必要地执行两次)
例如,在编写某个测试时,我需要一些临时文件来测试逻辑:
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);
当我使用File.Delete(file)
时,出现了FileNotFound
的异常,让我很吃惊!
发生的情况是files
枚举被迭代了两次(第一次迭代的结果只是没有被记住),并在每个新的迭代中重新调用Path.GetTempFilename()
,所以你会得到不同的临时文件名。
解决方法当然是通过使用ToArray()
或ToList()
来急切地枚举这个值:
var files = Enumerable.Range(0, 5)
.Select(i => Path.GetTempFileName())
.ToArray();
当你进行一些多线程的操作时,情况会变得更加可怕,比如:
foreach (var file in files)
content = content + File.ReadAllText(file);
然后你发现在所有的写入后content.Length
仍为0!你开始严格检查,确保没有竞争条件...浪费了一个小时后...你发现只是那个微小的Enumerable问题被忽略了....