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 Select 仅在查看 Enumerable 时引发 IOException

谁能解释为什么这是

正如许多人指出的那样,这是因为许多 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 设置为列表,则首先调用这些元素。然后你遍历所有元素。