Reputation: 5684
I would like to know if the following code is lazy evaluated or will crash in the way I handle possible exception of ReadAllLines()
. I know for sure that Where
clause is lazy evaluated but I'm not sure when I use it with ReadAllLines()
.
A possible explanation of how and why would be appreciated.
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...
}
Thanks in advance.
Upvotes: 5
Views: 2970
Reputation: 460238
File.ReadAllLines
is not lazy loaded, it loads all into memory.
string[] allLines = File.ReadAllLines(filePath);
If you want to use LINQ's deferred execution you can use File.ReadLines
instead:
var fileLines = File.ReadLines(filePath)
.Where(line =>
{
line = line.Trim();
return line.Contains("hello");
});
This is also documented:
The
ReadLines
andReadAllLines
methods differ as follows: When you useReadLines
, you can start enumerating the collection of strings before the whole collection is returned; when you useReadAllLines
, you must wait for the whole array of strings be returned before you can access the array. Therefore, when you are working with very large files, ReadLines can be more efficient.
But note that you have to be careful with ReadLines
since you cannot use it twice. If you try to "execute" it a second time you'll get an ObjectDisposedException
since the underlying stream is already disposed. Update This bug seems to be fixed.
This will cause an exception for example:
var lines = File.ReadLines(path);
string header = lines.First();
string secondLine = lines.Skip(1).First();
You cannot use it either to write to the same file since the stream is still open.
File.WriteAllLines(path, File.ReadLines(path)); // exception: being used by another process.
In these cases File.ReadAllLines
is more appropriate.
Upvotes: 10