在没有ToList()的情况下运行时,在Linq的SelectMany()中读取文件会抛出System.IO.IOException
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在没有ToList()的情况下运行时,在Linq的SelectMany()中读取文件会抛出System.IO.IOException相关的知识,希望对你有一定的参考价值。
我很好奇为什么下面的代码失败了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管道的末端抛出一个ToList()
,我避免了这个问题,但我无法弄清楚为什么会这样。
答案
你看到了Linq懒惰和物化的影响。
随着.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(懒惰)什么都不做:
// 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
打开。
另一答案
因为您尝试同时读取和写入同一文件,
ToList()
导致执行(枚举)发生在那一点,SelectMany返回一个IEnumerable
并等待它在File.WriteAllLines(filename, output)
执行(枚举)
以上是关于在没有ToList()的情况下运行时,在Linq的SelectMany()中读取文件会抛出System.IO.IOException的主要内容,如果未能解决你的问题,请参考以下文章