LINQ Select 仅在查看 Enumerable 时引发 IOException
本文关键字:IOException Enumerable Select LINQ | 更新日期: 2023-09-27 18:30:19
我目前正在使用 LINQ 将文件列表加载到 XDocuments 中,如下所示:
var fileNames = new List<string>(){ "C:'file.xml" };
var xDocs = fileNames.Select(XDocument.Load);
var xDocs2 = xDocs.ToList(); // Crashes here
如果我故意用不同的进程"锁定"其中一个文件,则只有在我真正开始查看我生成的 XDocuments 时(即调用 ToList() 时),才会抛出 IOException。
谁能解释为什么会这样,以及如何最好地处理此错误?如果可能的话,我仍然希望能够访问有效的XDocuments。
谁能解释为什么这是
正如许多人指出的那样,这是因为许多 LINQ 方法的所谓延迟执行。对于 instanse,Enumerable.Select
方法文档指出
此方法是使用延迟执行实现的。立即返回值是一个对象,用于存储执行操作所需的所有信息。在通过直接调用其 GetEnumerator 方法或在 Visual C# 中使用 foreach 或在 Visual Basic 中使用 For Each 枚举对象之前,不会执行此方法表示的查询。
而Enumerable.ToList
文档包含
ToList
(IEnumerable )方法强制立即进行查询计算,并返回包含查询结果的列表。可以将此方法追加到查询中,以获取查询结果的缓存副本。
因此,在ToList
调用期间,每个文件名实际上执行了XDocument.Load
。我想这涵盖了为什么部分。
以及如何最好地处理此错误?如果可能的话,我仍然希望能够访问有效的XDocuments。
我不知道在这种情况下"最好"是什么意思,但是如果您想忽略错误并包含"工作XDocuments",那么您可以使用这样的东西
var xDocs = fileNames.Select(fileName =>
{
try { return XDocument.Load(fileName); }
catch { return null; }
});
然后在处理列表时附加.Where(doc => doc != null)
或说明null
文档。
这就是为什么 linq .Select 是一个 IEnumerable,如果将 IEnumerable 设置为列表,则首先调用这些元素。然后你遍历所有元素。