在使用 LINQ Where 时,File.ReadAllLines 是否是惰性加载?

5
我想知道以下代码是否为惰性求值或者在我处理可能的ReadAllLines()异常的方式中会崩溃。我知道使用Where子句时它是惰性求值的,但我不确定当我将其与ReadAllLines()一起使用时是否仍然如此。关于如何以及为什么可能的解释将不胜感激。

File.ReadAllLines Exceptions

var fileLines = File.ReadAllLines(filePath).Where(line =>
{
    line = line.Trim();
    return line.Contains("hello");
});

string search;
try
{
    search = fileLines.Single();
}
catch (Exception exception)
{
    ...log the exception...
}

提前致谢。


1
T[]永远不会是惰性的,因为它需要一个连续的内存块。 - Caramiriel
1个回答

10

File.ReadAllLines 不是延迟加载的,它会将所有内容加载到内存中。

string[]  allLines = File.ReadAllLines(filePath);

如果您想使用LINQ的延迟执行,可以使用File.ReadLines代替:

var fileLines = File.ReadLines(filePath)
    .Where(line =>
    {
        line = line.Trim();
        return line.Contains("hello");
    });

这也有文档说明

ReadLinesReadAllLines方法有以下区别:当您使用ReadLines时,您可以在整个字符串集合返回之前开始枚举字符串集合;当您使用ReadAllLines时,您必须等待整个字符串数组被返回后才能访问该数组。因此,在处理非常大的文件时,ReadLines可能更有效率。

但请注意,您必须小心使用ReadLines,因为您不能两次使用它。如果尝试第二次“执行”它,则会收到ObjectDisposedException,因为底层流已被处置。 更新此错误似乎已经修复。

例如,这将导致异常:

var lines = File.ReadLines(path);
string header = lines.First();
string secondLine = lines.Skip(1).First();

由于流仍然处于打开状态,因此您也不能使用它来写入同一文件。

File.WriteAllLines(path, File.ReadLines(path)); // exception:  being used by another process.
在这些情况下,File.ReadAllLines更加合适。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接