我很好奇为什么下面一段代码因System.IO.IOException而失败,说该进程无法访问该文件,因为它正被另一个进程使用。
class Program
{
static void Main(string[] args)
{
const string filename = "tmp.txt";
File.AppendAllText(filename, "x");
var output = Enumerable.Range(0, 10).SelectMany(_ => File.ReadAllLines(filename));
File.WriteAllLines(filename, output);
}
}
只需在Linq Pipeline的末尾抛出一个ToList()
,我就可以避免这个问题,但我无法弄清楚为什么会出现这种情况。
答案 0 :(得分:4)
您会看到Linq laziness 和实现的效果。
添加.ToList()
后,我们output
具体化: Linq 执行查询(打开文件,填写集合和关闭文件):
// List<T> collection
var output = Enumerable
.Range(0, 10)
.SelectMany(_ => File.ReadAllLines(filename))
.ToList(); // <- We want a collection in memory
所以在写的时候,我们从内存中写入数据做磁盘
// Writing down the collection
File.WriteAllLines(filename, output);
没有.ToList()
Linq( lazy ) nothing :
// IEnumerable<T>
var output = Enumerable
.Range(0, 10)
.SelectMany(_ => File.ReadAllLines(filename)); // <- No more than a declaration
什么时候写
File.WriteAllLines(filename, output);
Linq 发现它必须提供应该写入的数据 - output
并开始执行此操作:它尝试打开文件但是失败了此操作,因为文件已使用File.WriteAllLines
打开。
答案 1 :(得分:0)
因为您试图同时读取和写入同一文件,
ToList()
导致执行(枚举)在此时发生,其中SelectMany返回IEnumerable
并等待其执行(枚举)File.WriteAllLines(filename, output)